Linux環境でcpanのArchive::Zipを使ってzipファイルを作成する際に、zipファイルの中に入れるファイル名をcp932にしたのだが、ファイルを解凍すると中のファイル名が見事に文字化けしていることがあった。
どうやらダメ文字(0x5c)が入るような”ソ”とか”能”とかがうまく表現できない。
ダメ文字とは
Shift_JIS(SJIS, cp932) の文字コードで、2byte目が0x5c の \ になっているものの俗称(だめ文字、駄目文字)
コード例
zip内のファイル名として、cp932にした文字列を設定する。
$file_name = Encode::encode("cp932" => "ソムリエ芸能界");
my $zip = Archive::Zip->new;
$zip->addString($content, $file_name);
文字化けの原因
Archive::Zipの下記の箇所で、\を/に置き換えていることが原因。
sub fileName {
my $self = shift;
my $newName = shift;
if (defined $newName) {
$newName =~ y{\\/}{/}s; # deal with dos/windoze problems
$self->{'fileName'} = $newName;
}
return $self->{'fileName'};
}
何だ?「deal with dos/windoze problems」って。
「dos/windozeの問題に対処する」ってことか。
自身の対応
おそらく、zip内ファイル名として、フォルダパスを指定した場合に不都合があった?(しかもwindows環境のみ)
と考えて、Windows環境でのみ、置換処理を実行するように変更してみたところ、自身のツールでは文字化けは解消された。
sub fileName {
my $self = shift;
my $newName = shift;
if (defined $newName) {
if ($^O eq 'MSWin32') {
$newName =~ y{\\/}{/}s; # deal with dos/windoze problems
}
$self->{'fileName'} = $newName;
}
return $self->{'fileName'};
}
補足
最近のzipフォーマットでは、ファイル名がutf8かどうかのフラグを持っていて、フラグがONになっていたらWindows10の標準解凍機能でもutf8のファイル名が文字化けせずに解凍できるらしい。(EFSフラグ)
おそらくArchive::Zipは未対応。
参考
考察
うーん、これはArchive::Zipの不具合でしょうか?
でも、いくらググっても、ダメ文字が化ける現象は自分以外には見つからなかった。
使い方が間違ってるんでしょうか?