Java・.Net Framework・DelphiのZIPファイル中のファイル名の文字コードを調べる

ZIPファイルに格納するファイル名の文字コードはWindowsとMacでは異なり、日本語版Windowsの圧縮フォルダはShiftJISで、Mac OS XのFinderはUTF-8で格納する。
そのため、Macで作成したZIPファイルをWindowsで解凍すると、ファイル名が文字化けすることがある。

ZIPファイルに格納するファイル名の文字コードをUTF-8とする仕様が2007年9月にようやくリリースされた。
仕様ではファイル名はUTF-8で格納するのが正しいことになる。
しかし、すでにファイル名をShiftJISで格納したZIPファイルが広く使われている。

参考:ZIP (ファイルフォーマット) – Wikipedia

主要なプログラム言語では、ZIPファイルのファイル名をどのように扱っているのだろうか。
標準ライブラリがファイル名をどのように格納するのかを調べてみた。

■Java 6のjava.util.zip

public static void compress() throws FileNotFoundException, IOException {
    File file = new File("C:\\test\\sample.zip");
    final ZipOutputStream zipOutStream = new ZipOutputStream(
        new BufferedOutputStream(new FileOutputStream(file)));
    ZipEntry doc = new ZipEntry("ドキュメント.txt");
    zipOutStream.putNextEntry(doc);
    zipOutStream.write(new String("テスト").getBytes());
    zipOutStream.closeEntry();
    zipOutStream.finish();
    zipOutStream.close();
}

java.util.zipではファイル名の文字コードを指定できず、ファイル名はUTF-8で格納する。
そのためjava.util.zipで作成したZIPファイルをWindowsで解凍すると文字化けが発生することがある。

■.NET Framework 4.5のSystem.IO.Compression.ZipArchive

static void compress()
{
    using (ZipArchive zip = ZipFile.Open(@"C:\test\sample.zip", 
        ZipArchiveMode.Create, Encoding.GetEncoding(932)))
    {
        ZipArchiveEntry readmeEntry = zip.CreateEntry("テスト.txt");
        using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
        {
            writer.WriteLine("テスト");
        }
    }
}

ZipFile.Openメソッドの引数にEncodingを指定することで、ファイル名の文字コードを指定することができる。
適切な文字コードを指定することで、文字化けを回避できる。

■Delphi XE3のSystem.Zip.TZipFile

procedure TForm1.Button1Click(Sender: TObject);
var
  zip: TZipFile;
  bytes: TBytes;
begin
  zip := TZipFile.Create;
  zip.Open('C:\test\sample.zip', zmWrite);
  zip.Add(TEncoding.Default.GetBytes('テスト'), 'ドキュメント.txt');
  zip.Close;
  zip.Free;
end;

System.Zip.TZipFileもJavaのjava.util.zipと同様、ファイル名の文字コードを指定することはできない。
やはり文字化けの可能性がある。

■Python 2.7のzipfile.ZipFile

#!/usr/bin/python
# -*- coding: Shift_JIS -*-
import zipfile

zip = zipfile.ZipFile('C:/test/sample.zip', 'w', zipfile.ZIP_DEFLATED)
info = zipfile.ZipInfo('ドキュメント.txt')
zip.writestr(info, 'テスト')
zip.close()

文字化けは発生しない。

試しにソースコードファイルの文字コードをUTF-8に変更すると、文字化けが発生した。

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import zipfile

zip = zipfile.ZipFile('C:/test/sample.zip', 'w', zipfile.ZIP_DEFLATED)
info = zipfile.ZipInfo('ドキュメント.txt')
zip.writestr(info, 'テスト')
zip.close()

ソースコードファイルのエンコーディングはShiftJISのまま、ZIPファイル中のファイル名をユニコード文字列で指定すると、文字化けが発生した。

#!/usr/bin/python
# -*- coding: Shift_JIS -*-
import zipfile

zip = zipfile.ZipFile('C:/test/sample.zip', 'w', zipfile.ZIP_DEFLATED)
info = zipfile.ZipInfo(u'ドキュメント.txt')
zip.writestr(info, 'テスト')
zip.close()

zipfile.ZipFileには、ファイル名の文字コードを指定する機能はない。
ファイル名がバイト列ならそのまま、ユニコード文字列ならUTF-8で格納しているようだ。
ファイル名を適切に指定すれば、文字化けを回避することができる。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です