UTF-8 の文字列チェック

よそからもらったデータの中に UTF-8 だが文字化けするデータがある。
日本語以外の文字が混入しているためだ。


1行ごとに UTF-8 から Shift_JIS (CP932) へ変換可能かどうかをチェックしたい。
Perl モジュールにそういった機能がありそうなのだが、探しきれなかったので自分で実装した。

http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP932.TXT
から CP932.TXT ダウンロードしておく。

use utf8;
binmode(STDOUT, ":utf8");

use strict;
use warnings;

my $utf8_file = "CP932.TXT";
my %utf8_map = ();

sub is_cp932 {
    my ($line) = @_;
    for (my $i = 0; $i < length($line); $i++) {
	my $s = substr($line, $i, 1);
	return 0 unless ($utf8_map{$s});
    }
    return 1;
}

open(CP932, $utf8_file);
while (my $line = <CP932>) {
    next if ($line =~ /^\#/);
    my ($c, $u, $tmp) = split(/\t/, $line, 3);
    next unless ($u =~ /^0x([A-F0-9]+)$/);
    $utf8_map{chr(hex($1))} = 1;
}
close(CP932);

while (my $line = <>) {
    utf8::decode($line);
    print $line if (is_cp932($line));
}