gorogoronyan FC2

Node.js: テキストの処理 (1)

TSVファイルの処理

Node.js で TSV (タブ区切りのテキスト) を出力したり、 TSV ファイルを読んで処理したりする話です。 プログラムの処理結果をリダイレクトでテキストファイルに保存したり、 ファイルを読んで処理したりします。 カンマ区切りのテキスト (CSV) もほぼ同じように処理できます。
JavaScript テキストデータを読んで処理

その1: ファイルリストを TSV で出力する

/*
node TestNodejs_tsv_filelist1.js (ディレクトリ名)
node TestNodejs_tsv_filelist1.js
node TestNodejs_tsv_filelist1.js /nodejs

・指定ディレクトリのファイルリストをTSV(タブ区切りのテキスト)
 で出力する。

・出力TSVのフォーマット
filename    size    time

  ディレクトリは size = -1
  time は更新時刻の long値
 */

const FS = require("fs");
const PATH = require("path");
let dir = process.argv[2];
if (!dir){
    dir = ".";
}

const list = FS.readdirSync(dir);
for (const name of list){
    try{
        const path = PATH.join(dir, name);
        const st = FS.statSync(path);
        const size = (st.isDirectory(path) ? -1 : st.size);
        console.log("%s\t%s\t%s", name, size, st.mtimeMs);
    }
    catch(e){
        //error への出力はリダイレクトでファイルに保存されない。
        console.error("err:"+e);
        //console.error("err:"+e.stack);  //エラーの発生箇所を表示
    }
}

実行例 (Windows10)
実行例 (Windows10)

その2: TSV ファイルを読んでテキストを整形する

/*
node TestNodejs_tsv_filelist2.js (TSVファイル名)
node TestNodejs_tsv_filelist2.js tmp.txt

・TSVのファイルリストを読んで、テキストを整形して表示する。
  TestNodejs_tsv_filelist1.js で出力した TSVファイルを使う。
 */

const FS = require("fs");
const text = FS.readFileSync(process.argv[2], { encoding:"utf8" });

//TSV を 2重配列に分割する
const mat = text.split(/\r\n|\n|\r/).map( s => s.split("\t"));
//TSVの最後の行が空行なので除去する
mat.pop();

for (const array of mat){
    try{
        const time = parseInt(array[2]);
        const date = createDateString( new Date(time));
        const size = createSizeString(array[1]);
        const name = array[0];
        console.log("%s %s %s", date, size.padStart(12), name);
    }
    catch(e){
        console.error("err:"+e);
    }
}

//サイズの文字列を作る。
function createSizeString(size){
    return (size < 0 ? "dir" : size);
}

//日付の文字列を作る。YYYY/MM/DD hh:mm:ss
function createDateString(date){
    const s = date.getFullYear()
    + "/" + ("0" + (date.getMonth() + 1)).slice(-2)
    + "/" + ("0" + date.getDate()).slice(-2)
    + " " + ("0" + date.getHours()).slice(-2)
    + ":" + ("0" + date.getMinutes()).slice(-2)
    + ":" + ("0" + date.getSeconds()).slice(-2);
    return s;
}

実行

node TestNodejs_tsv_filelist1.js > tmp.txt
node TestNodejs_tsv_filelist2.js tmp.txt
実行例 (Windows10)
実行例 (Windows10)

その3: TSV ファイルを読んで指定の列でソートする

/*
node TestNodejs_tsv_sort1.js (TSVファイル名) (オプション)
node TestNodejs_tsv_sort1.js tmp.txt index=1 type=int

◎オプション
・index=(数値)   省略した場合は 0。
  ソートする列のインデックス値、0から数える。

・type=string, int  省略した場合は string
  string : 文字列で比較
  int : 整数で比較
 */

const FS = require("fs");
const filepath = process.argv[2];
const options = parseOption(process.argv, 3);
const sortIndex = parseInt( getOption(options, "index", 0));
const sortType = getOption(options, "type", "string");

//ソート方法のテーブル
const sortTable = {
    "string" : (a, b) => a[sortIndex] > b[sortIndex] ? 1 : -1,
    "int" : (a, b) => parseInt(a[sortIndex]) - parseInt(b[sortIndex]),
};

const text = FS.readFileSync(filepath, { encoding:"utf8" });

//TSV を 2重配列に分割する。空行は除去する(途中の空行も除去する例)。
const mat = text.split(/\r\n|\n|\r/).filter( s => s ).map( s => s.split("\t"));

//並べ替える
mat.sort( sortTable[sortType]);

//結果を出力する
console.log( mat.map( a => a.join("\t")).join("\n"));


//コマンドラインのオプションを連想配列 {} にパースする
function parseOption(argv, startIndex){
    const map = {};
    for (let i=startIndex; i < argv.length; i++){
        const a = argv[i].split("=");
        const key = a[0];
        map[key] = a[1];
    }
    return map;
}

function getOption(options, key, defaultValue){
    const value = options[key];
    return (value ? value : defaultValue);
}

実行例

◎ファイル名でソートする
node TestNodejs_tsv_filelist1.js > tmp.txt
node TestNodejs_tsv_sort1.js tmp.txt > tmp2.txt
node TestNodejs_tsv_filelist2.js tmp2.txt

◎ファイルサイズでソートする
node TestNodejs_tsv_filelist1.js > tmp.txt
node TestNodejs_tsv_sort1.js tmp.txt index=1 type=int > tmp2.txt
node TestNodejs_tsv_filelist2.js tmp2.txt

◎日付でソートする
node TestNodejs_tsv_filelist1.js > tmp.txt
node TestNodejs_tsv_sort1.js tmp.txt index=2 type=int > tmp2.txt
node TestNodejs_tsv_filelist2.js tmp2.txt

ファイルサイズでソートした例
ファイルサイズでソートした例

関連

JSON で出力する

TSV ファイルの代わりに JSON で出力したり、JSON ファイルを読んで処理したりすることもできます。 単純なリストや 2重配列では間に合わないデータに適しています。
JavaScript: JSON シリアライズ

ファイルリストを JSON で出力する

/*
node TestNodejs_json_filelist1.js (ディレクトリ名)
node TestNodejs_json_filelist1.js
node TestNodejs_json_filelist1.js /nodejs

・指定ディレクトリのファイルリストを JSON で出力する。
  ディレクトリは size = -1
  time は更新時刻の long値
 */

const FS = require("fs");
const PATH = require("path");
let dir = process.argv[2];
if (!dir){
    dir = ".";
}

const list = FS.readdirSync(dir);
const array = [];
for (const name of list){
    try{
        const path = PATH.join(dir, name);
        const st = FS.statSync(path);
        const size = (st.isDirectory(path) ? -1 : st.size);
        const map = { "name": name, "size": size, "time" : st.mtimeMs };
        array.push(map);
    }
    catch(e){
        console.error("err:"+e);
    }
}

//JSON文字列を作る
const json = JSON.stringify(array);
console.log(json);


ファイルリストを JSON で出力
ファイルリストを JSON で出力

JSON テキストをオブジェクトに戻す

テキストファイルを読んで JSON.parse(text) でオブジェクトに戻します。

// たった 1行で簡単に Object に戻せます。
let obj = JSON.parse(text);

いろいろ

パイプ処理

上のサンプルでは、処理結果を 1度リダイレクトで テキストファイルに保存して、 次のコマンドプログラムでテキストファイルを読み直して処理しています。 これとは別にファイル保存を使わず、 処理結果を直接次のコマンドの入力データとして渡す処理方法もあります (パイプ処理)。 パイプ処理はコマンドラインの処理で多用されます。
Wikipedia: パイプ (コンピュータ)

関連

inserted by FC2 system