LoginSignup
9
9

More than 5 years have passed since last update.

JScriptでZIP圧縮&解凍(MS非推奨)

Last updated at Posted at 2014-04-07

はじめに

「Scripting.FileSystemObject」と「Shell.Application」を利用して、ZIPファイルの圧縮や解凍をやってみます。
「CopyHere」メソッドによるZIP処理はエラー処理が不完全な事を理由に、
Microsoftでは「サポート対象外」となっていますので、確実にやりたい場合は、
コマンドラインの圧縮モジュールなどを使ったほうが良いかもしれません。

ファイルオブジェクトとシェルオブジェクトを定義します。

// ファイルオブジェクト取得
var fso = new ActiveXObject("Scripting.FileSystemObject");
// シェル取得
var shell = new ActiveXObject("Shell.Application");

圧縮

圧縮は以下の手順で行います。

  1. 空のZIPファイルを作成する。
  2. 空のZIPファイルにファイルをコピーする。
  3. ZIP圧縮中は読み書き禁止なので、読み書き出来るまで待機する。

空のZIPファイルは「End of central directory record」というZIPファイル情報を
ファイル0個ととして、新規ファイルに書き込みます。
バイナリーコードですので、「fromCharCode」メソッドを利用していったん文字列として書き込んでいます。

また、読み書き出来るまで待機する方法として、読み書き可能としてファイルを開き
エラーが出るか、出ないかで判断しています。

サンプルコードでは、
第1引数に、ZIPファイル
第2引数に、ファイル、フォルダ、または、ファイルとフォルダのリスト
を指定するようになっています。

function zip(zipfile, files) {
    // ZIPに格納するアイテム
    var items = [];
    // ファイル存在チェック
    if (files) {
        // ファイル配列チェック
        if (files instanceof Array) {
            // 配列の場合はアイテムに設定
            items = files;
        } else {
            // 配列ではないので、配列に追加
            items.push(files);
        }
    }
    // ZIPファイル存在チェック
    if (!fso.FileExists(zipfile) && !fso.FolderExists(zipfile)) {
        var ts = null;
        try {
            // ZIPファイル生成
            ts = fso.OpenTextFile(zipfile, 2, true);
            // 空のZIPファイル生成
            ts.Write(String.fromCharCode(0x50, 0x4B, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
        } catch (e) {
            // エラーの場合
            throw e;
        } finally {
            try {
                if (ts != null) {
                    // ファイル閉じる
                    ts.Close();
                }
            } catch (e) {
                // エラーの場合
                throw e;
            }
        }
    }
    // 特殊フォルダ取得(ZIP)
    var zip = shell.NameSpace(zipfile);
    // アイテム数分ループ
    for (var i = 0; i < items.length; i++) {
        // ファイル又はフォルダ存在チェック
        if (fso.FileExists(items[i]) || fso.FolderExists(items[i])) {
            // ZIPファイルにコピー
            zip.CopyHere(items[i], 4);
            while (true) {
                // 待機
                WScript.Sleep(100);
                try {
                    // ZIPファイルが読書可能かチェック
                    fso.OpenTextFile(zipfile, 8, false).Close();
                    // 可能な場合は終了
                    break;
                } catch (e) {
                    // 不可能な場合は再度ループ
                }
            }
        }
    }
}

一応、「CopyHere」のオプション(第2引数)に、プログレスバー非表示(4)を設定しているんですが、
効いてないようです。

また、ZIPファイルの待機方法として、ZIPファイル内のファイル数で判定する方法もあるようです。

解凍

ZIPファイル内のファイルアイテムをフォルダにコピーします。

フォルダ生成には、前回作成した「createFolder」メソッドを利用しています。

こちらは、処理の待ち合わせが不要なようです・・・

function unzip(zipfile, folder) {
    // ZIPファイル存在&拡張子判定
    if (fso.FileExists(zipfile)
        && fso.GetExtensionName(zipfile).toLowerCase() == "zip") {
        var unzip = null;
        // パラメータチェック
        if (folder) {
            // フォルダ存在チェック
            if (!fso.FolderExists(folder)) {
                // フォルダが無い場合、生成
                createFolder(folder);
            }
            // ZIPファイル名設定
            unzip = folder;
        }
        // ZIPファイル存在チェック
        if (unzip != null) {
            // ZIP解凍
            shell.NameSpace(folder).CopyHere(shell.NameSpace(zipfile).Items(), 20);
        }
    }
}

コマンドラインを利用した圧縮&解凍

ここで記述すべき事ではないかもしれませんが、一応「7-Zip」のコマンドライン版にて、圧縮&解凍してみます。
実行するjsと同じフォルダに、「7za.exe」と圧縮対象のファイル「log.txt」があるこを条件とします。

事前に以下が定義されているとします。

// ファイルオブジェクト取得
var fso = new ActiveXObject("Scripting.FileSystemObject");
// Scriptのカレントパス取得
var folderName = fso.GetParentFolderName(WScript.ScriptFullName);
// 「WScript.Shell」生成
var wshell = new ActiveXObject("WScript.Shell");
  • 圧縮
// コマンド生成
var cmd = "\"" + folderName + "\\7za.exe\""   // 「7za.exe」パス
        + " a"                                // 追加
        + " \"" + folderName + "\\log.zip\""  // 圧縮ファイル
        + " \"" + folderName + "\\log.txt\""; // 圧縮対象ファイル
// コマンド実行
var exec = wshell.Exec(cmd);
// コマンド終了まで待機
while (exec.Status == 0) {
    // 待機
    WScript.Sleep(100);
}
  • 解凍
// コマンド生成
var cmd = "\"" + folderName + "\\7za.exe\""  // 「7za.exe」パス
        + " x"                               // 解凍
        + " \"" + folderName + "\\log.zip\"" // 圧縮ファイル
        + " -o\"" + folderName + "\\log\"";  // 解凍先
// コマンド実行
var exec = wshell.Exec(cmd);
// コマンド終了まで待機
while (exec.Status == 0) {
    // 待機
    WScript.Sleep(100);
}

コマンドラインですので、ここでは「7-Zip」版を使いましたがなんでも構いません。

9
9
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
9