Javascript, Snipet

Node.jsでテキスト読み込み

テキストファイルを読み込んで色々やるときに必要なことをメモ。

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で行ごとのストリームを作り、closeObservableの購読を止められるようにする。

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.') } );

コメントを残す