性能在很大程度上取决于所使用的缓冲区大小。默认情况下,缓冲区大小相当小。连接 2x2GB 文件时,我会使用大约 256kb 的缓冲区大小。缓冲区过大有时会失败,缓冲区过小则会获得比驱动器所能承受的吞吐量更低的吞吐量。
有了 gc
它就不仅仅是 -ReadCount
( -Read
PowerShell 5.0):
gc -ReadCount 256KB -Path $infile -Encoding Byte | ...
另外,我发现 Add-Content
对大量小文件进行逐个文件处理效果更好,因为只传输中等量的数据(200MB)时,我发现我的计算机出现 OOM、PowerShell 冻结并且 CPU 已满。
尽管 Add-Content
对于几百个文件来说随机失败了几次,并出现有关目标文件正在使用的错误,所以我添加了一个 while 循环和一个 try catch:
# Empty the file first
sc -Path "$path\video.ts" -Value @() -Encoding Byte
$tsfiles | foreach {
while ($true) {
try { # I had -ReadCount 0 because the files are smaller than 256KB
gc -ReadCount 0 -Path "$path\$_" -Encoding Byte | `
Add-Content -Path "$path\video.ts" -Encoding Byte -ErrorAction Stop
break;
} catch {
}
}
}
使用文件流则更快。您无法使用来指定缓冲区大小, [System.IO.File]::Open
但可以像 new [System.IO.FileStream]
这样:
# $path = "C:\"
$ins = @("a.ts", "b.ts")
$outfile = "$path\out.mp4"
$out = New-Object -TypeName "System.IO.FileStream" -ArgumentList @(
$outfile,
[System.IO.FileMode]::Create,
[System.IO.FileAccess]::Write,
[System.IO.FileShare]::None,
256KB,
[System.IO.FileOptions]::None)
try {
foreach ($in in $ins) {
$fs = New-Object -TypeName "System.IO.FileStream" -ArgumentList @(
"$path\$in",
[System.IO.FileMode]::Open,
[System.IO.FileAccess]::Read,
[System.IO.FileShare]::Read,
256KB,
[System.IO.FileOptions]::SequentialScan)
try {
$fs.CopyTo($out)
} finally {
$fs.Dispose()
}
}
} finally {
$out.Dispose()
}