テキストファイルを読み込んで色々やるときに必要なことをメモ。
Shift JIS を読み込む
Node.jsはそのままではShift JISを扱えない。いったんUTF-8に変換すれば扱えるので、文字コードの変換をしてくれる iconv-lite
の様なモジュールを使って変換する。
ストリームを使う場合は以下のようにする。以下はShift JISのファイルをUTF-8に変換するだけだが、ストリームのつなぎを変えれば色々できるようになる。
import { createReadStream, createWriteStream } from 'fs';
import { decodeStream, encodeStream } from 'iconv-lite';
const src = createReadStream('sample/src.txt' );
const dst = createWriteStream('sample/dst.txt');
const decode = decodeStream( 'Shift_JIS' );
const encode = encodeStream( 'utf-8' );
src.pipe( decode ).pipe( encode ).pipe( dst );
Shift JISを1行ずつ読み込むなら、Shift JISをUTF-8に変換してからReadlineで1行読んだ毎に発生するイベントで1行ずつの文字列を受け取る。
import { createReadStream } from 'fs';
import { decodeStream, encodeStream } from 'iconv-lite';
import { createInterface } from 'readline';
const src = createReadStream('sample/src.txt' );
const decode = decodeStream( 'Shift_JIS' );
const encode = encodeStream( 'utf-8' );
const lineReader = createInterface( src.pipe( decode ).pipe( encode ) );
lineReader.on( 'line', line => console.log(line + '!') ); // 行の末尾に ! を付ける
RxJS
で扱いたければ、line
イベントとclose
イベントを使ってObservable
を作る。line
で行ごとのストリームを作り、close
で Observable
の購読を止められるようにする。
import { createReadStream } from 'fs';
import { decodeStream, encodeStream } from 'iconv-lite';
import { createInterface } from 'readline';
import { fromEvent } from 'rxjs'
import { takeUntil } from 'rxjs/operators'
const src = createReadStream('sample/src.txt' );
const decode = decodeStream( 'Shift_JIS' );
const encode = encodeStream( 'utf-8' );
const lineReader = createInterface( src.pipe( decode ).pipe( encode ) );
const lineObservable = fromEvent( lineReader, 'line' ).pipe( takeUntil( fromEvent( lineReader, 'close' ) ) );
lineObservable.subscribe( line => console.log( line + '!' ), ( err )=> {}, () => { console.log('completed.') } );