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で格納しているようだ。
ファイル名を適切に指定すれば、文字化けを回避することができる。