LoginSignup
4
10

More than 3 years have passed since last update.

Node.jsでCSVファイルの文字コードやカラムを編集して保存する

Posted at

Node.jsを使って何かしらのcsvファイルをUTF-8に変換、さらにそのCSVファイルの指定した列を削除して、新しいファイルとして書き出す方法をご紹介します。

必要なモジュールのインストール

npm i csv --save
npm i iconv-lite --save
npm i encoding-japanese --save

csvは文字列をCSVファイルに変換するために、iconv-liteはファイルの文字コードを変換するために、encoding-japaneseはファイルの文字コードを判別するために使います。

今回行う処理

今回は入力されたSHIFT-JISのファイルをUTF-8に変換。さらには不必要な列を削除すると共に、1行目の項目名の変更などを行います。

具体例を出すと、下記のような形です。項目名を日本語➡️英語に編集。さらには不要なパスワード、住所・郵便番号の項目は削除、そして複数あるメールアドレスに関しては(メール2が配列になっているデータもあります)、それぞれ一行ずつにして表します。

想定としては、顧客リストなどの個人情報の入ったデータを、登録に必要な情報のみに変換して、何かしらの用途に用いるなどが考えられます。

ID,名前,メール1,パスワード,メール2,郵便番号,住所
1,Bob,test@bob.com,xxxxxx,test2@bob.com,xxx-xxxx,xxxxxxxx
2,Alice,test@alice.com,xxxxxx,test2@alice.com,xxx-xxxx,xxxxxxxx
3,Naomi,test@naomi.com,xxxxxx,test2@naomi.com,xxx-xxxx,xxxxxxxx
4,Key,test@key.com,xxxxxx,"test2@key.com,test3@key.com",xxx-xxxx,xxxxxxxx
5,Annna,test@annna.com,xxxxxx,"test2@annna.com,test3@annna.com,test4@annna.com",xxx-xxxx,xxxxxxxx

                ↓

id,name,email
1,Bob,test@bob.com
1,Bob,test2@bob.com
2,Alice,test@alice.com
2,Alice,test2@alice.com
3,Naomi,test@naomi.com
3,Naomi,test2@naomi.com
4,Key,test@key.com
4,Key,test2@key.com
4,Key,test3@key.com
5,Annna,test@annna.com
5,Annna,test2@annna.com
5,Annna,test3@annna.com
5,Annna,test4@annna.com


実際の処理

では実際の処理を紹介します。

const fs = require('fs');
const csv = require('csv');
const iconv = require('iconv-lite');
const encoding = require('encoding-japanese');
const parser = csv.parse((error, data) => {

    let newData = [];

    //ループしながら1行ずつ処理
    data.forEach((element, index, array) => {
        if(index == 0){
            let row = [];
            row.push('id');
            row.push('name');
            row.push('email');
            newData.push(row);
            return newData;
        }else{
            let row = [];
            createNewRow(element,row,element[2],newData);
            if(element[4].indexOf('@') != -1){
                if(element[4].indexOf(',') != -1){
                    var arr = element[4].split(',');
                    for(i=0; i < arr.length; i++){
                        let row = [];
                        createNewRow(element,row,arr[i],newData);
                    }
                }else{
                    let row = [];
                    createNewRow(element,row,element[4],newData);
                }
            }
        }
    })
    //write
    csv.stringify(newData,(error,output)=>{
        fs.writeFile('編集・変換後のファイル名.csv',output,(error)=>{
            console.log('処理データをCSV出力しました。');
        })
    })
})

var buf = fs.readFileSync('ファイル名.csv');
if(encoding.detect(buf) == 'SJIS'){

    fs.readFile('ファイル名.csv', function(err, data){
        if (err) throw err;
        var buf    = new Buffer.from(data, 'binary');  //バイナリバッファを一時的に作成する
        var retStr = iconv.decode(buf, "Shift_JIS"); //作成したバッファを使い、iconv-liteでShift-jisからutf8に変換
        fs.writeFile('変換後のファイル名.csv',retStr,(error)=>{
            console.log('処理データをCSV出力しました。');
        });
        fs.createReadStream('変換後のファイル名.csv').pipe(parser);
    });
}else if(encoding.detect(buf) == 'ASCII'){
    fs.createReadStream('ファイル名.csv').pipe(parser);
}else{
    console.log('この形式のファイルでは文字コードを変換できません。SHIFT-JISかUTF8のみ対応しています');
}

function createNewRow(element,row, email, newData){
    row.push(element[0]);
    row.push(element[1]);
    row.push(email);

    newData.push(row);
    return newData;
}

細かく分けて説明していきます。もともとShift-jisだったcsvファイルの文字コードをUTF8に変更します。


var buf = fs.readFileSync('ファイル名.csv');
if(encoding.detect(buf) == 'SJIS'){

    fs.readFile('ファイル名.csv', function(err, data){
        if (err) throw err;
        var buf    = new Buffer.from(data, 'binary'); 
        var retStr = iconv.decode(buf, "Shift_JIS"); //作成したバッファを使い、iconv-liteでShift-jisからutf8に変換
        fs.writeFile('変換後のファイル名.csv',retStr,(error)=>{
            console.log('処理データをCSV出力しました。');
        });
        fs.createReadStream('変換後のファイル名.csv').pipe(parser);
    });
}else if(encoding.detect(buf) == 'ASCII'){
    fs.createReadStream('ファイル名.csv').pipe(parser);
}else{
    console.log('この形式のファイルでは文字コードを変換できません。SHIFT-JISかUTF8のみ対応しています');
}

次は実際に編集をする処理です。



const parser = csv.parse((error, data) => {

    let newData = [];

    data.forEach((element, index, array) => {
        if(index == 0){
            let row = [];
            row.push('id');
            row.push('name');
            row.push('email');
            newData.push(row);
            return newData;
        }else{
            let row = [];
            createNewRow(element,row,element[2],newData);
            if(element[4].indexOf('@') != -1){
                if(element[4].indexOf(',') != -1){
                    var arr = element[4].split(',');
                    for(i=0; i < arr.length; i++){
                        let row = [];
                        createNewRow(element,row,arr[i],newData);
                    }
                }else{
                    let row = [];
                    createNewRow(element,row,element[4],newData);
                }
            }
        }
    })

    csv.stringify(newData,(error,output)=>{
        fs.writeFile('編集・変換後のファイル名.csv',output,(error)=>{
            console.log('出力成功');
        })
    })
})

function createNewRow(element,row, email, newData){
    row.push(element[0]);
    row.push(element[1]);
    row.push(email);

    newData.push(row);
    return newData;
}

csvモジュールの機能を使って、csvファイルをparseします。元のcsvファイルを一行ずつ処理していきます。一行目は大きく描き変えるために、新しい要素を直接書き込みます。二行目以降に関しては、必要な要素のみを抽出して処理します。

そしてメール2の項目の要素を持っている行に関しては、それをEmailに当てはめます。メール2項目を複数持っている物に関しては、そのようがカンマを持っていることで判別して、カンマで分割することで、配列要素にしそれを1つずつ行に入れていきます。

そして、それらのデータが入ったnewDataをfs.writeFileでcsvファイルとして書き出します。

以上になります。

参考記事

4
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
10