[PHP] UTF-8로 다국어를 파일 출력할 때 문자 깨짐

4290 단어 유니코드PHP
PHP에서 UTF-8로 중국어를 텍스트 파일로 출력하면 열리는 응용 프로그램에 의해 깨진 현상이 발생하는 사건을 만났다.

원래 프로그램


<?php

$filePath = 'mojibake.txt';
$value = '你好';

$fh = fopen($filePath, 'w');
fwrite($fh, mb_convert_encoding($value, 'UTF-8'));
fclose($fh);

도중의 처리는 생략하고 있다.
$ cat mojibake.txt
你好%

제대로 출력되고 있고, Mac의 텍스트 편집기에서 열어도 올바르게 표시된다. 그러나 이것을 Excel에서 열면 ...

이런 느낌으로 문자 깨져 버린다.

원인



어플리케이션에 의해, 유니코드의 부호화 방식을 판별할 수 없고, UTF-8·UTF-16·UTF-32를 판별할 수 없기 때문에, 문자 깨짐이 일어나 버린다.

해결책



위를 판별시키기 위해서, 파일 출력시의 선두에 BOM을 붙인다.

BOM이란?



BOM이란, Byte Order Mark의 약칭으로, Unicode의 encode 방식을 판별하기 위해서, 파일의 선두에 붙는 몇 바이트의 마크.

프로그램이 텍스트 데이터를 읽을 때, 그 선두의 몇 바이트로부터 그 데이터가 유니코드로 표현되고 있는 것, 또 부호화 형식(인코딩)으로서 어느 것을 사용하고 있는지를 판별할 수 있도록 한 것이다.
바이트 주문 마크 - Wikipedia

BOM은 다음과 같다.


인코딩 형식
엔디안의 구별
BOM


UTF-8

0xEF 0xBB 0xBF

UTF-16
BE
0xFE 0xFF

UTF-16
LE
0xFF 0xFE

UTF-32
BE
0x00 0x00 0xFE 0xFF

UTF-32
LE
0xFF 0xFE 0x00 0x00


이번은 UTF-8이므로, 0xEF 0xBB 0xBF 를 방금전의 파일의 선두에 붙이도록 한다.

수정된 프로그램


<?php

$filePath = 'mojibake.txt';
$value = '你好';

$fh = fopen($filePath, 'w');

// add BOM
fwrite($fh, "\xEF\xBB\xBF");

fwrite($fh, mb_convert_encoding($value, 'UTF-8'));
fclose($fh);

Excel에서 열어도 올바르게 표시됩니다.


BOM 첨부 여부 파일 정보 확인



파일에 BOM이 붙어 있는지는 명령으로 조사할 수 있다.
$ file mojibake.txt
mojibake.txt: UTF-8 Unicode (with BOM) text, with no line terminators

BOM이 있으면 with BOM가 표시됩니다.
$ file mojibake2.txt
mojibake2.txt: UTF-8 Unicode text, with no line terminators

BOM이 없으면 표시되지 않습니다.

좋은 웹페이지 즐겨찾기