파일을 읽어서 출력할 때 유니코드로 된 부분을 출력하려고 하면 머리가 아프지 않을 수가 없다. 하지만 우리의 아름다운 한글을 Perl이 출력하게 하려면 약간의 고통은 감내해야 한다. 한글 출력을 위해서는 크게 두 가지를 고려해야 하는데, 먼저 출력할 때 유니코드 인코딩으로 출력한다고 명시하는 것이다. 이것은 파일을 열 경우에
위와 같이 인코딩을 명시해주거나 그렇지 않을 경우엔
위처럼 binmode를 이용해서 지정해주는 방식이 있다. 물론 그냥 화면에 출력하고자 할 때에는 binmode 함수만을 써주되 RESULT 대신에 STDOUT을 쓰면 된다.
두 번째로 고려해야할 것은 좀 더 까다로운 문제인데, 파일에서 읽어들인 유니코드 바이트가 리틀 엔디안으로 돼 있을 경우 빅 엔디안으로 된 바이트로 바꾸는 것이다.
예를 들어, '반지의제왕'이라는 문자열의 실제 유니코드 값과 리틀 엔디안에서 저장되어 있을 때의 값은 다음과 같다.
문자열 |
반 |
지 |
의 |
제 |
왕 |
유니코드 값 |
bc18 |
c9c0 |
c758 |
c81c |
c655 |
리틀 엔디안 |
18bc |
c0c9 |
58c7 |
1cc8 |
55c6 |
그러니까 실제로 파일을 읽었을 땐 18bcc0c958c71cc855c6 이라는 값을 얻게 된다. 원래의 값으로 변화하려면, 이 값을 18bc c0c9 58c7 1cc8 55c6 과 같이 2바이트씩 끊은 뒤, 각각의 2바이트에서 바이트 두 개를 서로 바꿔주면 된다. 이런 기능을 해주는 라이브러리가 CPAN에 있을 것 같지만 간단히 아래와 같이 구현했다.
sub ltob
{
my $data = shift;
my $len = length($data);
my @result;
for(my $i=0; $i<$len; $i += 2)
{
my $tmp = substr($data, $i, 2); # Slices data by two(1-byte)
unshift @result, $tmp; # Puts the piece in the front of result array
}
my $result = join "", @result;
return $result;
}
# This subroutine makes hex values unicode string
sub unicode
{
my $data = shift;
my $len = length($data);
my $result;
for(my $i=0; $i<$len; $i += 4)
{
my $tmp = substr($data, $i, 4); # Slices data by four(2-byte)
$tmp = ltob($tmp);
$result .= chr(hex($tmp)); # makes string
}
return $result;
}
아래와 같이 unicode 함수를 이용해 출력하면 '반지의 제왕'이라는 결과를 얻을 수 있다.
'컴퓨터 > 프로그래밍' 카테고리의 다른 글
[Python] 파일 시그니처 확인 도구 (0) | 2021.01.18 |
---|---|
Perl 기본적인 내장변수, 함수 (0) | 2014.04.13 |