Perl / Encode : UTF-8 + BOM 문서를 decode 할 때 주의할 점
| 분류: Perl | 최초 작성: 2011-11-12 06:54:24 |
Perl 5.10 혹은 그 이전 버전에서 모두 발생합니다. 그 이후의 버전은 저도 모릅니다.
Perl의 Encode 모듈에서 decode 함수를 사용할 때, 만약 읽어들이는 문서가 UTF-8 문서라면 주의해야 한다. UTF-8의 경우 굳이 BOM(Byte Order Mark)을 붙이지 않아도 상관이 없는데, 일부 UTF-8 문서의 경우 UTF-8 인코딩을 사용하면서도 BOM이 붙어 있다. (예를 들면, 윈도우의 메모장으로 적성 후 UTF-8 인코딩 문서로 저장한 경우, 자동으로 BOM 이 포함되어 저장된다.)
이 문서를 Perl에서 읽을 경우, decode 되는 과정에서 decode 모듈이 이 BOM을 제거하지 않고 남겨두므로, 이 문자로 인하여 예상치 못한 문제가 발생할 수 있다. (문자열 처리 과정에서 필연적으로 오류를 만나게 된다!) 따라서
UTF-8 문서를 읽을 때에는, decode 한 후에 이 BOM 문자를 날려주는 작업이 별도로 이루어져야 한다.
sub FileRead {
my $RAW_DATA;
my $ENCODING;
open my $fHandle, "<", "$_[0]";
binmode $fHandle;
while(<$fHandle>){
$RAW_DATA .= $_;
}
close $fHandle;
undef $fHandle;
#------------------------
use Encode;
use Encode::Guess;
my $enc = guess_encoding($RAW_DATA, qw/ascii euc-kr utf8/);
if ( ref($enc) ) {
$ENCODING = $enc->name;
}
else {
$ENCODING = "Unknown";
}
undef $enc;
#------------------------
if ( $ENCODING eq "Unknown" ) {
print "Unknown Encoding!";
return -1;
}
else {
$RAW_DATA = decode( $ENCODING, $RAW_DATA );
}
# UTF8+BOM 주의
if ( $ENCODING eq "utf8" ) {
$RAW_DATA =~ s/\x{FEFF}//g;
}
undef $ENCODING;
#------------------------
return $RAW_DATA;
}
참고로,
역시 BOM이 붙어있는 UTF-16 (윈도우에서 기본으로 사용하는 유니코드. UTF-16 BE(Big Endian)와 UTF-16 LE(Little Endian)이 있으며, 윈도우는 후자를 사용한다.)
의 경우에는 decode 모듈이 자동으로 BOM을 날려주기 때문에, 위와 같은 번거로운 처리가 필요 없다.
* http://perldoc.perl.org/5.10.1/Encode/Guess.html
이 문서의 중간쯤에 관련 경고가 기술되어 있다 - "CAVEAT: Unlike UTF-(16|32), BOM in utf8 is NOT AUTOMATICALLY STRIPPED."
왜 잘 들여다보지도 않는 Guess 모듈 한구석에 적어놓은건지...