Windowsマシンで、完全メモリダンプを取得した時に、それを解析するために遠方へ送付するとかでDVDに焼かなきゃいけないんだけど、メモリを8GB積んでるので1枚に収まらない。みたいな場面でファイル分割するとき、適当に書いたファイル分割スクリプトだと、8GB超のファイルを一気にメモリに読み込んで分割するような動作になるので、メモリが足りなくて分割できないみたいなので、FileStream使って少しずつファイルを読みつつ、出力するPowerShellスクリプトを書いてみた。
[ファイル分割.ps1]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
param($filePath="",$splitSize=1024*1024*256) if( $filePath.Length -eq 0 ){ exit 1 } if( ( $splitSize % 1024 ) -ne 0 ){ $splitSize -= ($splitSize % 1024) } if( $splitSize -eq 0 ){ exit 1 } $mem = 1024*1024 $filecnt = 0 $resultBytes = 1 $filePath2 = "{0}_{1:000}" -F $filePath, $filecnt $bArr = New-Object byte[] -ArgumentList $mem $rStream = New-Object IO.FileStream( $filePath, [IO.FileMode]::Open, [IO.FileAccess]::Read ) $wStream = New-Object IO.FileStream( $filePath2, [IO.FileMode]::Append, [IO.FileAccess]::Write ) if( $rStream ) { for( $cnt = 0; $resultBytes -gt 0; $cnt++ ){ if( $splitSize -le ( $cnt * $mem ) ){ $wStream.Close() $wStream.Dispose() $cnt = 0 $filecnt++ $filePath2 = "{0}_{1:000}" -F $filePath, $filecnt $wStream = New-Object IO.FileStream( $filePath2, [IO.FileMode]::Append, [IO.FileAccess]::Write ) } $resultBytes = $rStream.Read( $bArr, 0, $mem ) $wStream.Write($bArr, 0, $resultBytes ) } $rStream.Close() $rStream.Dispose() } $wStream.Close() $wStream.Dispose() if( ( Get-ChildItem $FilePath2 ).Length -eq 0 ){ Remove-Item $filePath2 } |
実行は以下のように
.\ファイル分割.ps1 -filePath “分割したいファイル名” -splitSize 分割したいサイズ(Byte) |
特に理由もありませんが、デフォルトの分割サイズは256MBにしてあります。
特に理由はありませんが、分割サイズは1024バイト単位で指定してください。と言うか勝手になります。
一度に読み込むサイズは1MBにしていますが、実行時のメモリ使用量は70MB程度は食ってました。うちの環境では。
くっつけるときは普通にバッチとかで
copy /b “元のファイル名_*” ”くっつけた後のファイル名” |
とかで大丈夫だと思います。
ご使用の際は、何か問題が置きても気にしない心の大きな人間になってください。