問題が発生する環境・条件* 0.22.2 に、[日本語パッチ]を適用した環境 * 複数の文字コードが混在したメールを処理した場合に、Text::Kakasi による分かち書きを行った際に文字化けが生じる。 問題の詳細* Text::Kakasi の辞書を閉じない(パラメータを再設定しない)状態で、Encode モジュールで複数の文字コード間の変換を行うと、Text::Kakasi::do_kakasi で文字化けが発生する。 * Text::Kakasi 2.x では、内部で Encode モジュールを使うようになっており、この影響ではないかと考えられるが、詳しい原因については不明。 試したこと* [Text::Kakasi のドキュメント]によれば、「$Text::Kakasi::HAS_ENCODE を 0 にする」ことによって Encode 関係の機能を無効にできるということだが、下記のように設定してみても効果はなかった。 問題の解決策(暫定)* Text::Kakasi の処理の度に、パラメータを再設定することによって回避可能だが、パラメータを再設定するだけでは辞書ファイルが何度も開かれてしまって「Too many open files」エラーが発生。 * 辞書を毎回開いて閉じるようにすることによりすべての問題が解決するが、パフォーマンスが悪くなる。 問題検証のためのプログラムスクリプトと同じディレクトリに、shiftjis、jis の混在したテキストファイル「popfilecd.msg」があるという条件で検証。 <pre>#!/usr/bin/perl use strict; use Encode; use Encode::Guess; use Text::Kakasi; my %encoding_candidates = ( 'Nihongo' => [ 'shiftjis', 'euc-jp', '7bit-jis' ] ); $Text::Kakasi::HAS_ENCODE = 0; Text::Kakasi::getopt_argv("kakasi", "-w -ieuc -oeuc"); |
解決しました |
kakasi_test(); |
: この問題は解決し、パッチの内容は POPFile 0.22.3 へ取り込まれました。 |
Text::Kakasi::close_kanwadict(); sub kakasi_test { my $line; open(DB, "./popfilecd.msg"); while (<DB>) { $line = $_; $line = convert_encoding( $line, '7bitjis', 'euc-jp', '7bitjis', @{$encoding_candidates{'Nihongo'}} ); print $line; $line = Text::Kakasi::do_kakasi($line); print $line; } close(DB); } sub convert_encoding { my ( $string, $from, $to, $default, @candidates ) = @_; require Encode; require Encode::Guess; # First, guess the encoding. my $enc = Encode::Guess::guess_encoding( $string, @candidates ); |
問題が発生する環境・条件 |
if(ref $enc){ $from= $enc->name; print "Guessed encoding : $from\n"; } else { |
* 0.22.2 に、[日本語パッチ]を適用した環境 * ある種のメールを処理した場合に、Text::Kakasi による分かち書きを行った際に文字化けが生じる(他にも原因があるのかどうかについては不明)。 |
# If guess does not work, check whether $from is valid. |
問題の原因 |
if (!(Encode::resolve_alias($from))) { |
* Kakasi の漢字コード自動判定には問題があり、正しい漢字コードを Text::Kakasi に伝える必要があった。 |
# Use $default as $from when $from is invalid. |
問題の解決策 |
$from = $default; } } |
* 漢字コードを Text::Kakasi にちゃんと伝える。具体的には、Text::Kakasi::getopt_argv("kakasi", "-w -ieuc -oeuc"); としていた部分を、Text::Kakasi::getopt_argv("kakasi", "-w", "-ieuc", "-oeuc"); と修正した。 |
unless ($from eq $to) { my ($orig_string) = $string; |
関連情報 |
# Workaround for Encode::Unicode error bug. eval { Encode::from_to($string, $from, $to); }; $string = $orig_string if ($@); } return $string; }</pre> |
* [POPFile 全般 - 0.22.2 用日本語パッチ(試験公開)の動作テストをしていただける方募集] |