はじめに
Node.jsで重たいファイルを扱う際に、bashのsplit
コマンドっぽく、
ファイルを行ごとに分割したかったので作ったものを備忘録として残す。
Bashのコマンドとオプションを合わせたので、Bashっぽく使えるのがポイント。
コード
bashのsplitコマンド
split.sh
$ split [OPTION]... [FILE [PREFIX]]
オプション(一部)
- -l, --lines=NUMBER
- 分割するファイルの行単位
- -d, --numeric-suffixes
- 指定あり: [PREFIX000, PREFIX001, PREFIX002...]
- 指定なし: [PREFIXaaa, PREFIXaab, PREFIXaac...]
- -a, --suffix-length=N
- 出力ファイルに付加する文字列の長さ
Nodejs版
split.js
const fs = require('fs');
const readline = require('readline');
function createAlphabetSuffix(num, length) {
let i = num;
let str = '';
while (i > 0) {
str = String.fromCharCode(97 + (i % 26)) + str;
i = Math.floor(i / 26);
}
return str.padStart(length, 'a');
}
function createNumericSuffix(num, length) {
return String(num).padStart(length, '0');
}
module.exports = function split(file, options = {}) {
return new Promise((resolve) => {
let {
prefix = 'x',
lines = 100,
suffixLength = 3,
numericSuffixes = false
} = options;
const rs = fs.createReadStream(file);
const rl = readline.createInterface(rs);
let index = 0;
let ws;
rl.on('line', (line) => {
let i = index++;
if (i % lines === 0) {
ws && ws.close();
const suffixIndex = Math.floor(i / lines);
const suffix = numericSuffixes
? createNumericSuffix(suffixIndex, suffixLength)
: createAlphabetSuffix(suffixIndex, suffixLength);
ws = fs.createWriteStream(`${prefix}${suffix}`);
}
ws.write(line + '\n');
});
rl.on('close', () => {
ws && ws.close();
resolve();
});
});
};
オプション
オプション | 初期値 | 説明 |
---|---|---|
prefix | x | 出力するファイルのベース名 |
lines | 100 | 出力するファイルの行数 |
suffixLength | 3 | 出力ファイルに付与する文字列の長さ |
numericSuffixes | false | 出力ファイルに付与する文字列を数値にするか |
サンプル
useSplit.js
const split = require('./split');
(async () => {
await split('./largeFile.txt', {
prefix: 'smallFile',
lines: 10,
suffixLength: 4,
numericSuffixes: true
});
})();
result
$ node useSplit.js
$ ls | grep smallFile
# smallFile0000
# smallFile0001
# smallFile0002
# ...
最後に
意外に探しても見つからなかったので作ってみました。
他に良い方法があればご指摘ください。