使用Powershell连接二进制文件的最佳方法是什么? 我更喜欢简单易记和快速执行的单线程。
我提出的最好的是:
gc -Encoding Byte -Path ".\File1.bin",".\File2.bin" | sc -Encoding Byte new.bin
这似乎工作正常,但对于大文件来说速度非常慢。
答案 0 :(得分:27)
您正在采取的方法是我在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。
答案 1 :(得分:24)
这不是Powershell,但如果你有Powershell,你也有命令提示符:
copy /b 1.bin+2.bin 3.bin
正如Keith Hill所指出的,如果你真的需要从Powershell内部运行它,你可以使用:
cmd /c copy /b 1.bin+2.bin 3.bin
答案 2 :(得分:3)
我最近遇到了类似的问题,我想将两个大(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秒(确定)答案 3 :(得分:2)
性能在很大程度上取决于所使用的缓冲区大小。那些默认是相当小的。连接2x2GB文件我需要一个大约256kb的缓冲区。变大可能有时会失败,变小并且您的吞吐量会低于您的驱动器能力。
gc
与-ReadCount
-Read
不仅仅是gc -ReadCount 256KB -Path $infile -Encoding Byte | ...
(PowerShell 5.0):
Add-Content
另外,我发现Add-Content
更好,并且逐个文件地传输了很多小文件,因为只管道适量的数据(200MB),我发现我的计算机正在运行,PowerShell冻结和CPU满满的。
虽然# 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 {
}
}
}
对于几百个文件随机失败几次,并且有关目标文件正在使用的错误,所以我添加了一个while循环和一个try 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()
}
来指定:
private void getFriends() {
AccessToken accesstoken = AccessToken.getCurrentAccessToken();
GraphRequest.newMyFriendsRequest(accesstoken,
new GraphRequest.GraphJSONArrayCallback() {
@Override
public void onCompleted(JSONArray jsonArray, GraphResponse response) {
System.out.println("jsonArray: " + jsonArray);
System.out.println("GraphResponse: " + response);
}
}).executeAsync();
}