9250


こんにちは、[(node |
io).jsのStreamについて](https://ja.stackoverflow.com/questions/9118/node-io-
js%E3%81%AEstream%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)の質問をした者です。今、Streamの勉強をしているのですが上記の質問と同じようにhelloworld.txtを読み込み、"MyPush\n"という文字列を追加し、process.stdoutに表示するということを、
**pipeを使わず** 、代わりにwriteやreadを使って、やってみようと考えています。  
しかし、下記のコードを実行すると例のようなエラーが出ます。どうすればいいのでしょうか?

[code]

    
    var Transform = require("stream").Transform;
    var util = require("util");
    var fs = require("fs");
    var StringDecoder = require("string_decoder").StringDecoder;
    var process = require("process");
    util.inherits(MyStream, Transform);
    
    function MyStream() {
        Transform.call(this);
    }
    
    
    MyStream.prototype._transform = (chunk, encoding, callback) => {
        var data = chunk;
        var utf8decoder = new StringDecoder("utf8");
        var decoded_data = utf8decoder.write(data);
        var send_data = decoded_data + "MyPush\n";
        this.push(send_data);
        callback();
    }
    
    
    
    
    var readable_stream = fs.createReadStream("helloworld.txt");
    
    readable_stream.on("end", () => {
        console.log("end");
    });
    var mystream = new MyStream();
    mystream.on("readable", () => {
        var data = this.read();
        process.stdout.write(data);
    
    });
    readable_stream.on("readable", () => {
        var data = readable_stream.read();
        console.log("DATA", data); // return the null
        mystream.write(data);  
    });
    
    
[/code]

  

エラーの例

[code]

    
    _stream_writable.js:263
      var len = state.objectMode ? 1 : chunk.length;
                                            ^
    TypeError: Cannot read property 'length' of null
        at writeOrBuffer (_stream_writable.js:263:41)
        at MyStream.Writable.write (_stream_writable.js:210:11)
        at ReadStream. (/Users/username/jsworks/my_stream2.js:39:14)
        at emitNone (events.js:67:13)
        at ReadStream.emit (events.js:163:7)
        at emitReadable_ (_stream_readable.js:408:10)
        at emitReadable (_stream_readable.js:402:7)
        at onEofChunk (_stream_readable.js:385:3)
        at readableAddChunk (_stream_readable.js:129:7)
        at ReadStream.Readable.push (_stream_readable.js:109:10)
    
    
[/code]


CC BY-SA 3.0
2015-04-16T12:37:56.747
9234
2015-04-18T03:46:04.210
2017-04-13T12:52:38.920
-1
5246
question
javascript node.js iojs
JavaScriptのstreamでreadするとnullが返ってきてしまう。


改めて調べてみました。

Substack 氏によるハンドブックに[詳しい記述](https://github.com/substack/stream-
handbook#consuming-a-readable-stream)がありました。  
ストリーム終端でも `readable` イベントが発生し、この時は `this.read()` が `null` を返す、とのことです。

[code]

    var Transform = require("stream").Transform;
    var createReadStream = require("fs").createReadStream;
    var inherits = require("util").inherits;
    
    //------------------------------------------------------------------------------
    // 変換ストリームを定義
    function AppendMyPush() {
      Transform.call(this);
    }
    inherits(AppendMyPush, Transform);
    
    AppendMyPush.prototype._transform = function(chunk, encoding, callback) {
      // .toString()
      //   chunk が Buffer なら, UTF8でデコードされる。
      //   chunk が string なら, 単に自身を返す。
      // See Also: https://nodejs.org/api/buffer.html#buffer_buf_tostring_encoding_start_end
      //
      // chunk は null ではない
      // See Also: https://nodejs.org/api/stream.html#stream_transform_transform_chunk_encoding_callback
      this.push(chunk.toString() + "MyPush\n");
      callback();
    };
    
    //------------------------------------------------------------------------------
    // ファイルを読んで、変換ストリームを経由して標準出力に書き出す
    // source -> append -> sink の順につなぐ
    var source = createReadStream("helloworld.txt");
    var append = new AppendMyPush();
    var sink = process.stdout;
    
    // Readable イベントによってつなげる (source -> append)
    source.on("readable", function() {
      console.log("source readable enter");
    
      // ストリーム終端(これはファイルストリームなのでEOF)でも readable が発生する
      // このとき、this.read() の結果値は null になる
      var chunk = this.read();
      if (chunk != null) {
        console.log("  source readable read:", chunk);
        append.write(chunk);
      }
      else {
        console.log("  source readable reached end");
        // 終端を伝える
        append.end();
      }
    
      console.log("source readable exit");
    });
    
    
    // Readable イベントによってつなげる (append -> sink)
    append.on("readable", function() {
      console.log("  append readable enter");
    
      var chunk = this.read();
      if (chunk != null) {
        console.log("    append read:", chunk);
        sink.write(chunk);
      }
      else {
        console.log("    append readable reached end");
        // stdout を閉じるべきではない
      }
    
      console.log("  append readable exit");
    });
    
[/code]

実行結果:

[code]

    source readable enter
      source readable read: <Buffer 48 65 6c 6c 6f 20 57 6f 72 6c 64 21 0a>
      append readable enter
        append read: <Buffer 48 65 6c 6c 6f 20 57 6f 72 6c 64 21 0a 4d 79 50 75 73 68 0a>
    Hello World!
    MyPush
      append readable exit
    source readable exit
    source readable enter
      source readable reached end
      append readable enter
        append readable reached end
      append readable exit
    source readable exit
    
[/code]

ちなみに、質問で提示されているエラーは、null を受け入れないメソッドである `Writable::write()` に `null`
を与えているために発生しています。


CC BY-SA 3.0
2015-04-17T05:14:10.590
9250
2015-04-17T05:14:10.590
4809
9234
answer