ZIP中のファイル名の文字化け(Ruby編)

tmtms.hatenablog.com

という記事を書きましたが、今回はRubyでZIPファイルを作る時の話を。

RubyでZIPファイルを作るには、rubyzip というライブラリを使います。

% gem install rubyzip

次のようにしてZIPにファイルを追加できます。

require 'zip'

Zip::File.open('hoge.zip', Zip::File::CREATE) do |zip|
  zip.add('いろはにほへと.txt', '/path/to/いろはにほへと.txt')
end

Zip::File#add の第一引数はZIP内に記録されるファイル名、第二引数は実際のファイルのパスです。この二つのファイル名は同じである必要はありません。

ただし、この場合はUTF-8フラグがセットされません。つまりWindowsの標準機能で開くと文字化けしてしまいます。

UTF-8フラグを立てるには次のように Zip.unicode_names = true を指定します。

require 'zip'

Zip.unicode_names = true
Zip::File.open('hoge.zip', Zip::File::CREATE) do |zip|
  zip.add('いろはにほへと.txt', '/path/to/いろはにほへと.txt')
end

このように作成されたZIPファイルは最近のWindowsで(それとたぶんMacでも)開くことができます。

ただし、パッチがあたってない Windows 7 や、もう世界のどこでも動いていないはずの古いバージョンの Windows は UTF-8 に対応していないようなので、文字化けしてしまいます。

その場合はUTF-8フラグを立てずにファイル名をシフトJIS(CP932)に変換してやればいいです。

require 'zip'

Zip::File.open('hoge.zip', Zip::File::CREATE) do |zip|
  zip.add('いろはにほへと.txt'.encode('cp932'), '/path/to/いろはにほへと.txt')
end

なお、これはMacでは文字化けします(たぶん)。Macでも文字化けしないようです。

あらかじめZIPファイルを渡す相手の環境がわかっているのであれば、それに合わせて変更するのもいいでしょう。

Webアプリであれば User-Agent を見て動きを変えるのもいいかも知れませんね。