nodejs使用readline單行讀取並搭配iconv-lte解析big5等本地文件

在nodejs中,fs預設開啟格式為utf8,本身可以支援的格式如下:

  • ascii
  • base64
  • binary
  • hex
  • ucs2/ucs-2
  • utf16le/utf-16le
  • utf8/utf-8
  • latin1 (ISO8859-1, only in node 6.4.0+)

大部份情況下是不太需要調整
但在讀中文檔案上,往往會遇到big-5、gbk等檔案而無法正確解析

網路上使用fs.readFile等搭配iconv-lte應該有滿多相關資料,在此就不贅述(可至文末參考資料的stackOverflow參考)

但對於nodejs原生提供的readline module,卻似乎很少有相關資料
恰巧最近開發遇到類似問題,順便記錄一下解決方法


  1. 為方便其他程式使用es7語法(async,await),所以return promise
  2. 主要功能為讀到檔案後,逐行存入陣列並回傳
    完整程式碼如下
//檔案儲存成fileRead.js
const fs = require('fs');
const readline = require('readline');
const iconv = require('iconv-lite');


export async function readFileByLine(filePath) {
    return new Promise(function (resolve) {
        let lines = [];
        let rl = readline.createInterface({
+            input: fs.createReadStream(filePath).pipe(iconv.decodeStream('big5')),
            output: process.stdout,
            terminal: false
        });
        rl.on('line', function (line) {
            lines.push(line);
        });
        rl.on('close', function () {
            resolve(lines);
        });
    });

}

在input,使用createReadStream的pipe形成的鏈式流
將讀到的內容直接用iconv來解碼,就可以將檔案內容順利讀出以利後續作業!

其他程式呼叫使用方法如下

import { readFileByLine } from './fileRead' //上方檔名路徑

function async fileCheck(filePath){
    let fileContents = await readFileByLine(filePath);
                                   
    //此處加入對於內容篩檢等相關作業
    
    console.log(fileContents); //印出陣列內容
}

fileCheck('./testFile_BIG5.txt');

參考資料

stackoverflow/List of encodings that Node.js supports
RUNOOB/Node.js Stream