使用Powershell连接二进制文件的最佳方式是什么? 我更喜欢简单易记的快速执行的单线程。Powershell中快速简单的二进制连接文件
我想出的最好的是:
gc -Encoding Byte -Path ".\File1.bin",".\File2.bin" | sc -Encoding Byte new.bin
这似乎是工作正常,但与大文件非常慢。
使用Powershell连接二进制文件的最佳方式是什么? 我更喜欢简单易记的快速执行的单线程。Powershell中快速简单的二进制连接文件
我想出的最好的是:
gc -Encoding Byte -Path ".\File1.bin",".\File2.bin" | sc -Encoding Byte new.bin
这似乎是工作正常,但与大文件非常慢。
您采用的方法是我在PowerShell中执行此操作的方式。但是,您应该使用-ReadCount参数来提高性能。您也可以利用位置参数,以进一步缩短这个:
gc File1.bin,File2.bin -Enc Byte -Read 512 | sc new.bin -Enc Byte
关于使用-ReadCount参数的,我做了这个博客中,而以前,人们可能会发现有用 - Optimizing Performance of Get Content for Large Files。
这不是PowerShell中,但如果你有PowerShell的你也有命令提示符:
copy /b 1.bin+2.bin 3.bin
正如基思·希尔指出,如果你真的需要从内部PowerShell中运行它,你可以使用:
cmd /c copy /b 1.bin+2.bin 3.bin
副本中的cmd.exe固有的命令。你将不得不执行cmd/c copy/b 1.bin + 2.bin 3.bin – 2009-11-23 15:13:43
好的简单解决方案,适用于任何Windows计算机。 Upvoted,但接受基思,因为我问PS版本。 Thx – FkYkko 2009-11-23 15:38:51
还要注意'copy'支持通配符。因此,'copy/b * .bin out.bin'将连接所有bin文件,输出速度非常快(即比使用PowerShell快得多)。 – 2014-04-13 12:09:23
我最近有一个类似的问题,我想将两个大的(2GB)文件附加到一个文件(4GB)中。
我试图调整Get-Content的-ReadCount参数,但是我无法让它提高大文件的性能。
我去了以下解决方案:
function Join-File (
[parameter(Position=0,Mandatory=$true,ValueFromPipeline=$true)]
[string[]] $Path,
[parameter(Position=1,Mandatory=$true)]
[string] $Destination
)
{
write-verbose "Join-File: Open Destination1 $Destination"
$OutFile = [System.IO.File]::Create($Destination)
foreach ($File in $Path) {
write-verbose " Join-File: Open Source $File"
$InFile = [System.IO.File]::OpenRead($File)
$InFile.CopyTo($OutFile)
$InFile.Dispose()
}
$OutFile.Dispose()
write-verbose "Join-File: finished"
}
性能:
cmd.exe /c copy file1+file2 File3
大约5秒钟(最佳)gc file1,file2 |sc file3
1100左右秒(呸)join-file File1,File2 File3
各地16秒(OK)cmd.exe拷贝比原生PS cmdlet快很多倍 - 1.2MB/s与> 120Mb/s。并不奇怪考虑获取内容是如何工作的,甚至与-ReadCound参数 – 2017-10-23 20:13:25
性能很大程度上取决于所使用的缓冲区大小。这些默认情况下相当小。连接2x2GB文件我会采用大约256kb的缓冲区大小。越大,有时会失败,越小,吞吐量就会比驱动器的吞吐量降低。
随着gc
这会是与-ReadCount
不是简单-Read
(PowerShell的5.0):
gc -ReadCount 256KB -Path $infile -Encoding Byte | ...
另外,我发现Add-Content
要更好,要文件通过文件进行了大量的小文件,因为管道只有适量的数据(200MB),我发现我的计算机正在运行,PowerShell冻结且CPU处于充满状态。
虽然Add-Content
随机失败几百文件几次有关目标文件正在使用中的错误,所以我加了一个while循环和尝试捕捉:
# 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()
}
一个是猜测,这是由cmd.exe的复制命令使用一个非常类似的方法 – 2017-10-23 20:14:59
我只是跑这对我的示例文件和命令采取9分钟3秒钟,列入-read PARAM的去了。这是一个x25米的驱动器。尼斯。你得到我的接受。 – FkYkko 2009-11-23 15:36:20
只用一行就可以加入一个跨越23个文件的4.4gb iso。重新组装好文件,并使用1024字节块在笔记本上花了35分钟。 – 2012-07-12 21:56:27
我猜这是有效的,因为管道发送.net对象sc?当我试图将二进制数据传输到c程序时,我注意到我只获得每个字节的前7位,因为“|”调用编码。 – johnnycrash 2014-07-14 21:52:49