2011-09-25 11 views
8

大きなファイル(utf8)があります。私はfs.createReadStreamは、大きなファイルを読むためにストリームを作成できますが、同期されていないことを知っています。だから私はfs.readSyncを使用しようとしますが、読むテキストは"迈�"のように壊れています。nodejs同期行ごとに大きなファイルを読み込みますか?

var fs = require('fs'); 
var util = require('util'); 
var textPath = __dirname + '/people-daily.txt'; 
var fd = fs.openSync(textPath, "r"); 
var text = fs.readSync(fd, 4, 0, "utf8"); 
console.log(util.inspect(text, true, null)); 
+0

ファイルはutf8でエンコードされていますか? – thejh

+0

はい、Unicode(UTF-8)とUnix(LF) – nroe

+0

私はあなたが "同期"ではなく "同期"を意味すると思います。 – hippietrail

答えて

4

使用readFileSync

fs.readFileSync(ファイル名、[符号化]) fs.readFileの同期バージョン。ファイル名の内容を返します。

エンコードが指定されている場合、この関数は文字列を返します。 それ以外の場合は、バッファを返します。

ノードを使用しているので、私は非同期関数の使用をお勧めします。

+2

ファイルが大きいです、私は思うfs.readFileSyncは良い考えではありません。 – nroe

+1

@nroe、なぜあなたは同期読み取りを要求していますか?もちろん、大きなファイルでは動作しません。 – Tom

+2

@Tom、nroeは、読取り呼び出しに対する戻り値として行を受け取ることを望んでいる可能性があります。これを実装するいくつかのコードは[このブログの投稿](http://blog.jaeckel.com/2010/03/i-tried-to-find-example-on-using-node.html)(私のものではありません)で利用できます。 –

1

二つの潜在的な問題、

  1. あなたは
  2. 最初の4バイトがうまく大の場合
9

UTF8の文字をフォーマットする(UTF8が固定されていない長さ)することはできませんスキップしませんでした先頭にBOMを3バイトファイル、readFileSyncはメモリ内のファイル全体を読み込むので不便です。異なる同期アプローチは、一度に小さなビットのデータを読み取って、それが来るときに線を処理することを繰り返してreadSyncを呼び出すことです。次のコードビットは、このアプローチを実装し、同期ファイル「test.txtの」から一度に1つの行を処理します。

var fs = require('fs'); 
var filename = 'test.txt' 

var fd = fs.openSync(filename, 'r'); 
var bufferSize = 1024; 
var buffer = new Buffer(bufferSize); 

var leftOver = ''; 
var read, line, idxStart, idx; 
while ((read = fs.readSync(fd, buffer, 0, bufferSize, null)) !== 0) { 
    leftOver += buffer.toString('utf8', 0, read); 
    idxStart = 0 
    while ((idx = leftOver.indexOf("\n", idxStart)) !== -1) { 
    line = leftOver.substring(idxStart, idx); 
    console.log("one line read: " + line); 
    idxStart = idx + 1; 
    } 
    leftOver = leftOver.substring(idxStart); 
} 
+0

すごく、ありがとう! – Benvorth

7

使用私は簡単なバージョンJBコーンの答えを建てhttps://github.com/nacholibre/node-readlines

var lineByLine = require('n-readlines'); 
var liner = new lineByLine('./textFile.txt'); 

var line; 
var lineNumber = 0; 
while (line = liner.next()) { 
    console.log('Line ' + lineNumber + ': ' + line.toString('ascii')); 
    lineNumber++; 
} 

console.log('end of line reached'); 
2

ことバッファー上でsplit()を使用します。私が試した大きなファイルで動作します。

/* 
* Synchronously call fn(text, lineNum) on each line read from file descriptor fd. 
*/ 
function forEachLine (fd, fn) { 
    var bufSize = 64 * 1024; 
    var buf = new Buffer(bufSize); 
    var leftOver = ''; 
    var lineNum = 0; 
    var lines, n; 

    while ((n = fs.readSync(fd, buf, 0, bufSize, null)) !== 0) { 
     lines = buf.toString('utf8', 0 , n).split('\n'); 
     lines[0] = leftOver+lines[0];  // add leftover string from previous read 
     while (lines.length > 1) {   // process all but the last line 
      fn(lines.shift(), lineNum); 
      lineNum++; 
     } 
     leftOver = lines.shift();   // save last line fragment (may be '') 
    } 
    if (leftOver) {       // process any remaining line 
     fn(leftOver, lineNum); 
    } 
} 
+0

可能なウィンドウの行末をサポートするために 'split( '\ n')'を 'split(/ \ r?\ n /)'に変更することもできます。 – rob3c

関連する問題