1

Node.js を使用して 500MB の Apache ログ ファイルを処理しようとしました。

ip.ip.ip.ip - - [02/Aug/2012:05:01:17 -0600] "GET /path/of/access/ HTTP/1.1" 302 26

ip.ip.ip.ip - - 02/Aug/2012:05:01:17 GET /path/of/access/ HTTP/1.1 302 26

、次に別のテキスト ファイルに書き込みます。

メモリ制御とパフォーマンスを向上させるために、 and を使用fs.createReadStreamしましたが、スクリプトがエラーで終了するため、fs.createWriteStream最初の行を に書き込むことしかできませんでした。output.txt

{ [Error: EBADF, write] errno: 9, code: 'EBADF' }

ここに、デバッグに役立つ情報を投稿しました。

の頭input.txt:

ip.ip.ip.ip - - [02/Aug/2012:05:01:17 -0600] "GET /path/of/access/ HTTP/1.1" 302 26
ip.ip.ip.ip - - [02/Aug/2012:05:01:17 -0600] "GET /path/of/access/ HTTP/1.1" 302 26
ip.ip.ip.ip - - [02/Aug/2012:05:01:17 -0600] "GET /path/of/access/ HTTP/1.1" 302 26
ip.ip.ip.ip - - [02/Aug/2012:05:01:17 -0600] "GET /path/of/access/ HTTP/1.1" 302 26
ip.ip.ip.ip - - [02/Aug/2012:05:01:17 -0600] "GET /path/of/access/ HTTP/1.1" 302 26
ip.ip.ip.ip - - [02/Aug/2012:05:01:17 -0600] "GET /path/of/access/ HTTP/1.1" 302 26
ip.ip.ip.ip - - [02/Aug/2012:05:01:18 -0600] "GET /path/of/access/ HTTP/1.1" 302 26

の内容output.txt:

ip.ip.ip.ip - - [02/Aug/2012:05:01:17 -0600] "GET /path/of/access/ HTTP/1.1" 302 26

スクリプト全体:

var fs = require('fs');
var data ='';
var n=0;                    //For line control
var r = fs.createReadStream('./input.txt',{
    encoding: 'ascii',
    start:0,
    // end: 100000,
});
var w = fs.createWriteStream('./output.txt',{
    encoding:'ascii'
});
function put(line){         //write into w;
    ++n;
    w.write(line+'\n');
}
function end(){
    r.destroy();
    w.destroy();
}
function onData(chunk){
    var hasNewline = chunk.indexOf('\n')!==-1;
    if(hasNewline){
        var arr = chunk.split('\n');
        var first = arr.shift();
        var last = arr.pop();
        data+=first;
        put(data);          //write a complete line
        arr.forEach(function(line){
            put(line);      //write a complete line
        });
        data=last;
    }else{
        data+=chunk;
    }
    if(n>100){
        end();
    }
}
function onErr(e){
    console.log(e);
}

r.addListener( "data", onData);
r.addListener( "end", end);
r.addListener('error',onErr);
w.addListener('error',onErr);
4

1 に答える 1

2

私が見ることができる2つの問題があります。

1つ目は、end関数がdestroyReadStreamを呼び出すことですが、通常、これはendイベントからトリガーされます。つまり、ストリームはすでに閉じており、destroy自動的に呼び出されます。これは、それr.destroyが2回呼び出され、エラーが発生することを意味します。これが、印刷されたエラーの原因です。

2番目の問題はdestroy、WriteStreamを呼び出していることです。そのためのドキュメントを読むことをお勧めします:http://nodejs.org/api/stream.html#stream_stream_destroy_1

具体的Any queued write data will not be sentには、これが出力の一部が欠落している理由です。

基本的destroyに、ReadStreamを呼び出すのは、あなたの場合のように、早く終了したい場合のみにしてくださいn > 100。次に、代わりにWriteStreamを使用するendため、ストリームにはバッファリングされたすべてのデータを書き込む時間があります。

これは簡略化されたバージョンですが、同じように機能するはずです。errorとにかくエラーが自動的にコンソールに出力されるので、バインドも気にしません。

var fs = require('fs');
var data ='';
var n=0;                    //For line control

var r = fs.createReadStream('./input.txt',{
    encoding: 'ascii',
    start:0,
    // end: 100000,
});

var w = fs.createWriteStream('./output.txt',{
    encoding:'ascii'
});

r.addListener( "data", function(chunk){
    data += chunk;
    var lines = data.split('\n');
    data = lines.pop();

    lines.forEach(function(line){
      if (!r.readable) return; // If already destroyed
      if (n >= 100) {
          // Stop any more 'data' events and close the file.
          // This will also trigger 'close' below and close the writestream.
          r.destroy();
          return;
      }

      n++;
      w.write(line + '\n');
    });
});
r.addListener( "end", function(){
    // When we hit the end of the file, close the write stream,
    // and write any remaining line content
    w.write(data);
});
r.addListener("close", function(){
  w.end();
});
于 2012-08-14T05:50:20.397 に答える