Windows PowerShell V4.0以前の機能を使って、大きなサイズのファイルを圧縮する

Windows PowerShell V4.0以前の機能を使って、大きなサイズのファイルを圧縮する
Windowsでコマンド実行でファイルを圧縮しようと思ったら結構ハマったのでメモ。


課題

Windowsの機能だけで、コマンドラインからファイル圧縮を実現する方法をいろいろ試してみたところ、以下のような問題が発生しました。

ファイルを圧縮するようなOS標準コマンドが無い

エクスプローラー上で右クリックから圧縮を選べば簡単にできるzipファイル。

しかし、コマンドラインからファイルを圧縮するためには、PowerShellやVBスクリプトを駆使しなければ出来ません。

今回はPowerShellを使ってみました。

圧縮ファイルの2GB制限?

PowerShell V5.0には「Compress-Archive」という便利なコマンドレットがあるのですが、2GBを超えるような大きなファイルは圧縮できません。

CreateEntryFromFile」を使用しても同じくエラーが発生します。

例外が発生しました: "ストリームが長すぎます。"

大きなファイルを圧縮する場合、Compress-Archive、CreateEntryFromFileは使えないようです。

※そもそもWindowsではファイルサイズが大きければ大きいほど、圧縮ファイルが破損する可能性があるとのこと。

PowerShellのバージョンが古い環境でも動作させたい

PowerShellのバージョンが古くても動作するように、COMを使ったやり方を試してみました。


CopyHereを使ってzipを作成するプログラム

実行を確認した環境は以下の通りです。
  • Windows Server 2016、PowerShell V5.0
  • Windows 7、PowerShell V2.0

PowerShellのソースは以下の通り。

#ZIPファイルのヘッダ(空のzipファイル)
$zipheader = [char]80 + [char]75 + [char]5 + [char]6
$cnt = 0
while($cnt -ne 18){
    $zipheader += [char]0
    $cnt++
}

#空のZIPを作成
set-content "D:\Backup\Backup.zip" ($zipheader)

#shell.application生成
$shApp = new-object -com shell.application

 #空のZIPを取得
$zipPack = $shApp.NameSpace("D:\Backup\Backup.zip")

#圧縮対象ファイルをZIPへ格納
$zipPack.CopyHere("D:\Backup\EXPORACLE.DMP")

while($zipPack.Items().Count -ne 1)
{
    #追加完了まで待機する
    start-sleep -milliseconds 500
}

ファイルフォーマットで、ヘッダが「PK\005\006」だと空のアーカイブと認識されます。
([char]80は"P"、[char]75は"K")

まず空のZIPを作成した後、CopyHereメソッドで圧縮したいファイルをZIPに追加。

CopyHereは非同期なので、ZIPにファイルが追加されるまでSleepを入れながらZIPの中身をチェックしています。

まとめ

2GBを超えるファイルを圧縮してみましたが、この方法だとエラーは出ませんでした。

上記プログラムで圧縮したファイルを解凍しても、今のところ問題は発生していません。

Microsoftサポートには「正しく処理できない場合があります」という文章がありますので、使用は自己責任で。
>>CopyHere メソッドから Zip ファイルを処理することはできません

以上

<スポンサーリンク>


0 件のコメント :

コメントを投稿