Home > Latest topics

Latest topics > nsIZipWriterを使ってFirefoxでZIPアーカイブを作る

宣伝1。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能! シス管系女子って何!? - 「シス管系女子」特設サイト

宣伝2。Firefox Hacks Rebooted発売中。本書の1/3を使って、再起動不要なアドオンの作り方のテクニックや非同期処理の効率のいい書き方などを解説しています。既刊のFirefox 3 Hacks拡張機能開発チュートリアルと併せてどうぞ。

Firefox Hacks Rebooted ―Mozillaテクノロジ徹底活用テクニック
浅井 智也 池田 譲治 小山田 昌史 五味渕 大賀 下田 洋志 寺田 真 松澤 太郎
オライリージャパン

nsIZipWriterを使ってFirefoxでZIPアーカイブを作る - Jul 16, 2009

nsIZipWriterを使えばアドオンでZIPアーカイブを作れるということを割と最近になってやっと知ったので、アドオンのXPIへのパッケージングまで全部アドオンでできるやん!と思ったんだけど、使い方がよく分からんかったので、実験と練習もかねてコンテキストメニュー拡張の短縮構文で使える汎用的な処理を書いてみた。

要点だけ抜き出すとこんな感じ。

// aSources = nsIFileの配列
// aZipFile = 作るZIPアーカイブのnsIFile
// aCompressionLevel = 圧縮率(0で無圧縮、9で最大圧縮、デフォルトは6)
zipFilesAs : function(aSources, aZipFile, aCompressionLevel) 
{
    // Firefox 3以降じゃないと動かないよ!
    if (!('nsIZipWriter' in Components.interfaces))
        throw Components.results.NS_ERROR_NOT_IMPLEMENTED;

    if (!aSources || !aSources.length || !aZipFile) return;

    if (aZipFile.exists() && !this.isZipFile(aZipFile))
        aZipFile.remove(true);

    const PR_RDWR        = 0x04;
    const PR_CREATE_FILE = 0x08;
    const PR_APPEND      = 0x10;
    const PR_TRUNCATE    = 0x20;

    var writer = Components
                    .classes['@mozilla.org/zipwriter;1']
                    .createInstance(Components.interfaces.nsIZipWriter);

    if (aCompressionLevel === void(0))
        aCompressionLevel = writer.COMPRESSION_DEFAULT;

    // 新規ZIPアーカイブと既存のZIPアーカイブではフラグが違う
    var flags = aZipFile.exists() ?
                    PR_RDWR | PR_APPEND :
                    PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE ;
    writer.open(aZipFile, flags);

    aSources.forEach(function(aFile) {
        var entry = this+aFile.leafName;
        // フォルダに対応するエントリの有無を調べる時は、
        // エントリ名の末尾に「/」が必要
        var entryForCheck = aFile.isDirectory() ? entry+'/' : entry ;

        // すでにあるエントリで、フォルダではない物は削除。
        // (フォルダを削除しないのは、内容をマージするため)
        if (!aFile.isDirectory() && writer.hasEntry(entryForCheck))
            writer.removeEntry(entry, false);

        // 新しいエントリを追加
        if (!writer.hasEntry(entryForCheck))
            writer.addEntryFile(entry, aCompressionLevel, aFile, false);

        if (aFile.isDirectory()) {
            var files = aFile.directoryEntries;
            while (files.hasMoreElements())
            {
                arguments.callee.call(
                    entry+'/',
                    files.getNext().QueryInterface(Components.interfaces.nsILocalFile)
                );
            }
        }
    }, '');

    writer.close();
},

// ファイルの内容を実際にZIPアーカイブとして読んでみて、ZIPアーカイブかどうか調べる
isZipFile : function(aFile)
{
    var isZip = false;

    if (!aFile || !aFile.exists()) return isZip;

    var reader = Components
                    .classes['@mozilla.org/libjar/zip-reader;1']
                    .createInstance(Components.interfaces.nsIZipReader);
    try {
        reader.open(aFile);
        try {
            var entries = reader.findEntries('*');
            while (entries.hasMore())
            {
                entries.getNext();
                isZip = true;
                break;
            }
            if (!isZip) {
                entries = reader.findEntries('*/');
                while (entries.hasMore())
                {
                    entries.getNext();
                    isZip = true;
                    break;
                }
            }
        }
        catch(e) {
        }
        reader.close();
    }
    catch(e) {
    }

    return isZip;
},
分類:Mozilla > XUL, , , , , , , 時刻:18:42 | Comments/Trackbacks (0) | Edit

Comments/Trackbacks

TrackBack ping me at


の末尾に2014年1月19日時点の日本の首相のファミリーネーム(ローマ字で回答)を繋げて下さい。例えば「noda」なら、「2009-07-16_zipwriter.trackbacknoda」です。これは機械的なトラックバックスパムを防止するための措置です。

Post a comment

writeback message: Ready to post a comment.

2014年1月19日時点の日本の首相のファミリーネーム(ひらがなで回答)

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のつぶやき

オススメ

Mozilla Firefox ブラウザ無料ダウンロード