0
Help us understand the problem. What are the problem?

posted at

BOM付きCSVファイルを読み込むときの注意点

環境

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が付いているかを判断することはできません。

test_bom.csv
長浜,みかん,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なし)長浜」と「長浜」の文字列をと比較しているため、正しくマッチされました。

コード

sample.js
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
マッチしない
米原
彦根
---------
長浜
米原
彦根

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
0
Help us understand the problem. What are the problem?