NodeJS를 사용하여 프런트엔드 도구를 작성할 때 가장 일반적으로 사용되는 텍스트 파일은 텍스트 파일이므로 파일 인코딩 문제도 관련됩니다. 일반적으로 사용되는 텍스트 인코딩은 UTF8 및 GBK이며 UTF8 파일에는 BOM이 포함될 수도 있습니다. 다른 인코딩으로 텍스트 파일을 읽을 때 파일 내용을 JS에서 사용하는 UTF8 인코딩 문자열로 변환해야 정상적으로 처리될 수 있습니다.
BOM 제거
BOM은 텍스트 파일의 헤더에 있는 유니코드 문자("uFEFF")인 유니코드 인코딩을 사용하여 텍스트 파일을 표시하는 데 사용됩니다. 다양한 유니코드 인코딩에서 BOM 문자에 해당하는 이진 바이트는 다음과 같습니다.
Bytes Encoding ---------------------------- FE FF UTF16BE FF FE UTF16LE EF BB BF UTF8
따라서 파일에 BOM이 포함되어 있는지 여부와 텍스트 파일의 처음 몇 바이트가 동일한 것을 기준으로 사용할 유니코드 인코딩을 결정할 수 있습니다. 그러나 BOM 문자는 파일 인코딩을 표시하는 역할을 하지만 파일 내용의 일부는 아닙니다. 텍스트 파일을 읽을 때 BOM이 제거되지 않으면 특정 사용 시나리오에서 문제가 발생할 수 있습니다. 예를 들어 여러 JS 파일을 하나의 파일로 병합한 후 파일에 BOM 문자가 포함되어 있으면 브라우저 JS 구문 오류가 발생합니다. 따라서 NodeJS를 사용하여 텍스트 파일을 읽을 때 일반적으로 BOM을 제거해야 합니다. 예를 들어 다음 코드는 UTF8 BOM을 식별하고 제거하는 기능을 구현합니다.
function readText(pathname) { var bin = fs.readFileSync(pathname); if (bin[0] === 0xEF && bin[1] === 0xBB && bin[2] === 0xBF) { bin = bin.slice(3); } return bin.toString('utf-8'); }
GBK에서 UTF8로
NodeJS는 텍스트 파일을 읽을 때나 Buffer를 문자열로 변환할 때 텍스트 인코딩 지정을 지원하지만 안타깝게도 GBK 인코딩은 NodeJS 자체 지원 범위에 속하지 않습니다. 따라서 일반적으로 타사 패키지 iconv-lite를 사용하여 인코딩을 변환합니다. NPM을 사용하여 패키지를 다운로드한 후 다음과 같이 GBK 텍스트 파일을 읽는 함수를 작성할 수 있습니다.
var iconv = require('iconv-lite'); function readGBKText(pathname) { var bin = fs.readFileSync(pathname); return iconv.decode(bin, 'gbk'); }
단일 바이트 인코딩
때로는 읽어야 하는 파일이 어떤 인코딩을 사용하는지 예측할 수 없어 올바른 인코딩을 지정할 수 없는 경우가 있습니다. 예를 들어, 처리해야 하는 CSS 파일 중 일부는 GBK로 인코딩되고 일부는 UTF8로 인코딩됩니다. 파일의 바이트 내용을 기반으로 텍스트 인코딩을 어느 정도 추측할 수는 있지만 여기서 소개할 내용은 다소 제한적이지만 훨씬 간단한 기술입니다.
먼저 텍스트 파일에 Hello World와 같은 영어 문자만 포함되어 있으면 GBK 인코딩이나 UTF8 인코딩을 사용하여 파일을 읽는 데 문제가 없다는 것을 알고 있습니다. 이는 이러한 인코딩에서 ASCII0~128 범위의 문자가 동일한 단일 바이트 인코딩을 사용하기 때문입니다.
반면, 텍스트 파일에 중국어나 기타 문자가 있더라도 처리해야 할 문자가 주석과 문자열을 제외한 JS 코드와 같이 ASCII0~128 범위에만 있는 경우에는 다음을 사용할 수 있습니다. 단일 바이트로 균일하게 인코딩하면 파일의 실제 인코딩이 GBK인지 UTF8인지 신경 쓸 필요가 없습니다. 다음 예에서는 이 접근 방식을 보여줍니다.
1. GBK 인코딩 소스 파일 내용:
var foo = '中文';
2. 해당 바이트:
76 61 72 20 66 6F 6F 20 3D 20 27 D6 D0 CE C4 27 3B
3. 싱글바이트 인코딩을 사용하여 읽은 후 얻은 콘텐츠:
var foo = '{乱码}{乱码}{乱码}{乱码}';
4. 대체 콘텐츠:
var bar = '{乱码}{乱码}{乱码}{乱码}';
5. 단일 바이트 인코딩을 사용하여 저장한 후 해당 바이트:
76 61 72 20 62 61 72 20 3D 20 27 D6 D0 CE C4 27 3B
6. GBK 인코딩을 사용하여 콘텐츠를 읽고 가져옵니다.
var bar = '中文';
여기서 트릭은 0xEF보다 큰 단일 바이트가 단일 바이트 인코딩으로 구문 분석되는 왜곡된 문자에 관계없이 이러한 왜곡된 문자가 동일한 단일 바이트 인코딩을 사용하여 저장될 때 그 뒤에 있는 해당 바이트는 변경되지 않고 유지된다는 것입니다.
NodeJS에는 이 메서드를 구현하는 데 사용할 수 있는 바이너리 인코딩이 제공되므로 다음 예제에서는 이 인코딩을 사용하여 위 예제에 해당하는 코드를 작성하는 방법을 보여줍니다.
function replace(pathname) { var str = fs.readFileSync(pathname, 'binary'); str = str.replace('foo', 'bar'); fs.writeFileSync(pathname, str, 'binary'); }