【perlメモ】文字コードが混在してしまったログファイルの処理
本来セキュリティ的にない方がいいというかあってはならないのですが、昔作ったプログラムで適当にログを取ってたりすると文字コードが混在していた入します。一応文字コードはutf8で保存しているので定石どおりに下の様なスクリプトで読み込んでみようとすると
#!/usr/local/bin/perl
use strict;
use warnings;
use utf8;
use Encode;
my @dlist=();
open(FILE,'<:utf8′,’inputlog.txt’);
@dlist = <FILE>;
close(FILE);
下のような感じでエラーがズラズラと出てしまいます。
utf8 "\xE3" does not map to Unicode at ooo3.cgi line 14, <FILE> line 274.
utf8 "\xC2" does not map to Unicode at ooo3.cgi line 14, <FILE> line 313.
utf8 "\xE3" does not map to Unicode at ooo3.cgi line 14, <FILE> line 428.
utf8 "\xE3" does not map to Unicode at ooo3.cgi line 14, <FILE> line 674.
utf8 "\x82" does not map to Unicode at ooo3.cgi line 14, <FILE> line 892.
utf8 "\xB4" does not map to Unicode at ooo3.cgi line 14, <FILE> line 1147.
utf8 "\x99" does not map to Unicode at ooo3.cgi line 14, <FILE> line 1582.
utf8 "\x82" does not map to Unicode at ooo3.cgi line 14, <FILE> line 1798.
utf8 "\xE3" does not map to Unicode at ooo3.cgi line 14, <FILE> line 1926.
utf8 "\x83" does not map to Unicode at ooo3.cgi line 14, <FILE> line 2051.
utf8 "\x82" does not map to Unicode at ooo3.cgi line 14, <FILE> line 2162.
utf8 "\x8E" does not map to Unicode at ooo3.cgi line 14, <FILE> line 2448.
utf8 "\xC2" does not map to Unicode at ooo3.cgi line 14, <FILE> line 2542.
utf8 "\xE9" does not map to Unicode at ooo3.cgi line 14, <FILE> line 2589.
utf8 "\xA5" does not map to Unicode at ooo3.cgi line 14, <FILE> line 2661.
文字コードがutf8で割り当てられている範囲にないという感じのエラーの様です。
ログを見てみると所々で文字化けしている箇所があったりします。
ログを整理したいので、単純に文字化けしているところは切り捨てて、生きている部分だけを別ファイルに保存したいのです。
実際には上に載せているソースより複雑でいらない行を除外する処理とかソートの処理とか入っていて、どこでエラーが出ているのか最初よくわからなくてハマってたのですが、調べてみると下でopenした時点でもうエラーが出てしまっていることがわかったので、
open(FILE,'<:utf8′,’inputlog.txt’);
open時には文字コードを指定しないようにして1行毎にdecode_utf8して、なおかつイレギュラーな文字コードはエラーになるようにして正常なもの取り出して別のファイルに保存する様にしたのが下のソース。必要に応じてループの中に入らないデータを除外する処理を入れると必要なデータだけ選別出来ると思います。
#!/usr/local/bin/perl
use strict;
use warnings;
use utf8;
use Encode qw( encode decode encode_utf8 decode_utf8 :fallback_all);
my @dlist=();
open(FILE,’inputlog.txt’);
while(<FILE>){
eval{
my $utf8 = decode_utf8($_, DIE_ON_ERR | LEAVE_SRC);
push(@dlist,$utf8);
};
#warn $@ if($@);
}
close(FILE);
open(FILE,’>:utf8′,’result.txt’);
print FILE @dlist;
close(FILE);
とりあえずこれでうまくいきました。
◎参考にさせて頂いた偉大なサイト。
◇404 Blog Not Found:perl – EncodeでXSSを防ぐ
◇404 Blog Not Found:#perl – utf8::decode()ではなくEncode::decode_utf8()を使うべき理由
タグ : perlメモ
文字コードが正しいかどうかは、
表示してほしい文字が表示されているかどうかです。
文字コードとは、文字を番号であらわす仕組みです。
例えば、ある文字コードでは「亜」と表示される番号が、
別の文字コードでは「胃」と表示される。
文字コードの番号自体はどちらも一緒です。
どちらの文字コードが正しいのか、
それは人の都合で決めるものなので、
(表示されてほしい文字が表示されているかどうか)
全ての文字について人間の判断が必要です。
前後の文脈を見ればある程度予測できますが、
厳密には、文字を入力した人にしかわかりません。
また、たまたま一方の文字コードにしか存在しない番号であれば、
エラーが出るのでわかりますが、
前述の例のように、
文字コードによって異なる文字が表示される番号については、
エラーは発生しません。
人の判断が必要です。