【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で割り当てられている範囲にないという感じのエラーの様です。

ログを見てみると所々で文字化けしている箇所があったりします。

20100286

ログを整理したいので、単純に文字化けしているところは切り捨てて、生きている部分だけを別ファイルに保存したいのです。

実際には上に載せているソースより複雑でいらない行を除外する処理とかソートの処理とか入っていて、どこでエラーが出ているのか最初よくわからなくてハマってたのですが、調べてみると下で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()を使うべき理由

Encode

Perl 5.8.x Unicode関連

PerlでUTF-8の文字コードを扱う

タグ :