使用PowerShell连接二进制文件的最佳方法是什么?我更喜欢一个简单的记忆和快速执行的一行程序。我想到的最好的办法是:
gc -Encoding Byte -Path ".\File1.bin",".\File2.bin" | sc -Encoding Byte new.bin
这似乎工作正常,但对于大文件非常慢。
omvjsjqw1#
你采取的方法是我在PowerShell中使用的方法。但是,您应该使用-ReadCount参数来提高性能。您还可以利用位置参数来进一步缩短此时间:
gc File1.bin,File2.bin -Encoding Byte -Read 512 | sc new.bin -Encoding Byte
-AsByteStream
-Encoding Byte
Set-Content
sc
关于-ReadCount参数的使用,我在不久前写了一篇博客文章,人们可能会发现-Optimizing Performance of Get Content for Large Files很有用。
soat7uwm2#
它不是PowerShell,但如果你有PowerShell,你也有命令提示符:
copy /b 1.bin+2.bin 3.bin
正如基思希尔指出的那样,如果你真的需要从PowerShell内部运行它,你可以用途:
cmd /c copy /b 1.bin+2.bin 3.bin
mrphzbgm3#
我最近遇到了类似的问题,我想将两个大文件(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
gc file1,file2 |sc file3
join-file File1,File2 File3
50few1ms4#
性能在很大程度上取决于所使用的缓冲区大小。默认情况下,这些都相当小。连接2x2GB的文件,我需要一个大约256kb的缓冲区大小。变大有时可能会失败,变小,你会得到更少的吞吐量比你的驱动器的能力。使用gc,将与-ReadCount一起使用,而不仅仅是-Read(PowerShell 5.0):
gc
-ReadCount
-Read
gc -ReadCount 256KB -Path $infile -Encoding Byte | ...
另外,我发现Add-Content更好,对于很多小文件来说,一个文件接一个文件,因为管道传输的数据量很小(200MB),我发现我的电脑正在运行,PowerShell冻结,CPU满负荷运行。尽管Add-Content在几百个文件中会随机失败几次,并出现目标文件正在使用的错误,但我还是添加了一个while循环和一个try catch:
Add-Content
# 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],如下所示:
[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() }
w46czmvw5#
你也可以用这个方法连接任何类型的文件。不是那么快,只是另一种方式来做它
cmd /c type file1 file2 file3 file4 > outfile
或者,如果存在多个复制任务,则可以使用作业来加快速度。
$jobs=@() $Files=@( @("d:\path\app1.rar","d:\path\app2.rar","d:\path\app3.rar","d:\path\appOutFile.rar"),@("c:\users\user\desktop\file1.iso","c:\users\user\desktop\file2.iso","c:\users\user\desktop\file3.iso","c:\users\user\desktop\isoOutFile.iso"),@("c:\users\user\video\video1.mp4","c:\users\user\video\video2.mp4","c:\users\user\video\mp4OutFile.mp4")) $totalMb=0 foreach($Group in $Files){ $sources=$Group|select -first ($Group.Length-1) $sources|%{ $totalMb+=(get-Item $_).Length/1mb } $sources=$(($sources -replace "^|$",[char]34)-join"+") $destination=[char]34+($Group|select -last 1)+[char]34 cmd /c type nul> $destination $jobs+=start-job -scriptBlock { param($src,$dst) &cmd.exe "/c copy /b $src $dst" } -arg $sources,$destination # $jobs+=start-job -scriptBlock { param($src,$dst) &cmd.exe "/c type $($src -replace '`"\+`"','`" `"') > $dst" } -arg $sources,$destination } "Total MegaBytes To Concatenate is: $( [math]::Truncate($totalMb) )MB" while ( $($jobs|% {$_.state -eq "running"}) -contains $true ) {"still concatenating files...";start-sleep -s 2} "jobs finished !!!";$jobs|receive-job;$jobs|remove-job -force
5条答案
按热度按时间omvjsjqw1#
你采取的方法是我在PowerShell中使用的方法。但是,您应该使用-ReadCount参数来提高性能。您还可以利用位置参数来进一步缩短此时间:
-AsByteStream
而不是-Encoding Byte
;此外,Set-Content
小程序的sc
别名已被删除。关于-ReadCount参数的使用,我在不久前写了一篇博客文章,人们可能会发现-Optimizing Performance of Get Content for Large Files很有用。
soat7uwm2#
它不是PowerShell,但如果你有PowerShell,你也有命令提示符:
正如基思希尔指出的那样,如果你真的需要从PowerShell内部运行它,你可以用途:
mrphzbgm3#
我最近遇到了类似的问题,我想将两个大文件(2GB)附加到一个文件(4GB)中。
我尝试调整Get-Content的-ReadCount参数,但无法提高处理大文件的性能。
我采用了以下解决方案:
性能:
cmd.exe /c copy file1+file2 File3
约5秒(最佳)gc file1,file2 |sc file3
大约1100秒(讨厌)join-file File1,File2 File3
约16秒(正常)50few1ms4#
性能在很大程度上取决于所使用的缓冲区大小。默认情况下,这些都相当小。连接2x2GB的文件,我需要一个大约256kb的缓冲区大小。变大有时可能会失败,变小,你会得到更少的吞吐量比你的驱动器的能力。
使用
gc
,将与-ReadCount
一起使用,而不仅仅是-Read
(PowerShell 5.0):另外,我发现
Add-Content
更好,对于很多小文件来说,一个文件接一个文件,因为管道传输的数据量很小(200MB),我发现我的电脑正在运行,PowerShell冻结,CPU满负荷运行。尽管
Add-Content
在几百个文件中会随机失败几次,并出现目标文件正在使用的错误,但我还是添加了一个while循环和一个try catch:使用文件流仍然要快得多。您不能使用
[System.IO.File]::Open
指定缓冲区大小,但可以使用new [System.IO.FileStream]
,如下所示:w46czmvw5#
你也可以用这个方法连接任何类型的文件。
不是那么快,只是另一种方式来做它
或者,如果存在多个复制任务,则可以使用作业来加快速度。