環境
node.js v10.19.0
Ubuntu 20.4
はじめに
UTF-8のCSVファイルには、BOM付きのCSVファイルととBOMなしのCSVファイルの2種類が存在しています。CSVファイルを読み込んで中身を取得する場合、BOM付きのときは、BOMを削除しないとデータが正しく取得されないことになります。(BOMが付いたままでデータを取得すると、処理に誤りが生じることになります)
CSVファイルを読み込んだら、まずは、BOMが付いているかどうか判断して、付いていれば、データを取得する前に削除する必要があります。
BOMが付いているかどうかを判断する方法は、CSVファイルをダブルクリックして、Excelで開いて、文字化けが起こればBOMが付いていない。文字化けが起こらなければ、BOMが付いていると判断することができます。
CSVファイルをエディタで開いて中身を確認しても、BOMは改行コードのように、目で見えるものではないため、エディタでは直接確認することはできません。
コードの解説
test_bom.csvをBOM付きで作成します。test_bom.csvをエディタで開くと、このようなデータが作られます。1行目の先頭(長浜の左側)にはBOMが付いています。しかし、エディタで見る分にはBOMが付いているかを判断することはできません。
長浜,みかん,500
米原,バナナ,1000
彦根,りんご,3000
test_bom.csvを作成した後、test_bom.csvを読み込んで、各行の1カラム目だけを取得します。つまり、「長浜、米原、彦根」のデータだけを取得します。
test_bom("")を実行して、test_bom.csvを読み込んだとき、1行目に「長浜」が存在しているがマッチしませんでした。「(BOM付き)長浜」と「長浜」の文字列とを比較していたことが原因です。このようにBOMが付いたままになっていると、1行目の処理で誤りが発生する原因となります。
次に、test_bom("BOM")を実行します。2回目にtest_bom.csvを読み込みんだときは、先頭行のBOMを削除しています。2回目の処理では、「(BOMなし)長浜」と「長浜」の文字列をと比較しているため、正しくマッチされました。
コード
function test_bom(flg) {
var fs = require('fs');
var fd;
var file = __dirname + "/test_bom" + ".csv";
var ary = [];
ary.push("\ufeff" + "長浜,みかん,500");
ary.push("米原,バナナ,1000");
ary.push("彦根,りんご,3000");
fs.writeFileSync(file, "");
fd = fs.openSync(file, "w");
fs.writeSync(fd, ary.join("\n"), 0);
fs.closeSync(fd);
var text = fs.readFileSync(file, 'utf8');
var lines = text.toString().split('\n');
// BOMが付いていれば削除
if (flg == "bom") {
lines[0] = (lines[0].includes("\ufeff")) ? lines[0].replace("\ufeff", "") : lines[0];
}
for (let idx in lines) {
let ary_match = ["長浜", "米原", "彦根"];
let data = lines[idx].split(",")[0];
if (ary_match.includes(data)) {
console.log(data);
} else {
console.log("マッチしない");
}
}
}
test_bom("");
console.log("---------");
test_bom("bom");
結果
$node sample.js
マッチしない
米原
彦根
---------
長浜
米原
彦根