Powershell中快速简单的二进制连接文件

时间:2009-11-23 14:44:10

标签: powershell

使用Powershell连接二进制文件的最佳方法是什么? 我更喜欢简单易记和快速执行的单线程。

我提出的最好的是:

gc -Encoding Byte -Path ".\File1.bin",".\File2.bin" | sc -Encoding Byte new.bin

这似乎工作正常,但对于大文件来说速度非常慢。

4 个答案:

答案 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();
}