web-dev-qa-db-ja.com

Node.jsストリームの内容を文字列変数に読み取ります

SMTPメールをキャプチャし、メールデータを処理するnode.jsプログラムをハッキングしています。 「smtp-protocol」ノードライブラリはメールデータをストリームとしてライブで提供します。node.js初心者として、そのストリームを文字列変数に書き込む方法がわかりません。私は現在、次の行を使用してstdoutに書き込んでいます:

stream.pipe(process.stdout, { end : false });

先ほど言ったように、このストリームデータを文字列変数に書き込む必要があります。これは、ストリームが終了したら使用します。

大いに感謝ヘルプ!

71
obrienmd

重要なのは、これら2つの ストリームイベント を使用することです。

  • イベント:「データ」
  • イベント:「終了」

stream.on('data', ...)の場合、データデータをバッファ(バイナリの場合)または文字列に収集する必要があります。

on('end', ...)の場合は、バッファを完了した状態でコールバックを呼び出すか、インライン化してPromisesライブラリを使用してreturnを使用できる場合。

28
ControlAltDel

これが上記の回答(リンクが壊れている)よりも便利であることを願っています。

また、文字列の連結は文字列部分を収集するための効率的な方法ではありませんが、簡単にするために使用されます(そして、おそらくコードは効率を気にしません)

var string = '';
stream.on('data',function(data){
  string += data.toString();
  console.log('stream data ' + part);
});


stream.on('end',function(){
 console.log('final output ' + string);
});
59
Tom Carchrae

上記のどれも私にはうまくいきませんでした。 Bufferオブジェクトを使用する必要がありました。

  const chunks = [];

  readStream.on("data", function (chunk) {
    chunks.Push(chunk);
  });

  // Send the buffer or you can put it into a var
  readStream.on("end", function () {
    res.send(Buffer.concat(chunks));
  });
47
Ricky

別の方法は、ストリームをプロミスに変換し(以下の例を参照)、then(またはawait)を使用して、解決された値を変数に割り当てることです。

function streamToString (stream) {
  const chunks = []
  return new Promise((resolve, reject) => {
    stream.on('data', chunk => chunks.Push(chunk))
    stream.on('error', reject)
    stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')))
  })
}

const result = await streamToString(stream)
37

通常、この単純な関数を使用して、ストリームを文字列に変換しています。

function streamToString(stream, cb) {
  const chunks = [];
  stream.on('data', (chunk) => {
    chunks.Push(chunk.toString());
  });
  stream.on('end', () => {
    cb(chunks.join(''));
  });
}

使用例:

let stream = fs.createReadStream('./myFile.foo');
streamToString(stream, (data) => {
  console.log(data);  // data is now my string variable
});
19
dreampulse

Nodejsから documentation これを行う必要があります-エンコーディングが単なるバイト数であることを知らずに、常に文字列を覚えておいてください:

var readable = getReadableStreamSomehow();
readable.setEncoding('utf8');
readable.on('data', function(chunk) {
  assert.equal(typeof chunk, 'string');
  console.log('got %d characters of string data', chunk.length);
})
7
Sebastian J.

ストリームには、単純な.toString()関数(これは理解できません)も.toStringAsync(cb)関数(これは理解できません)のようなものもありません。

そこで、独自のヘルパー関数を作成しました。

var streamToString = function(stream, callback) {
  var str = '';
  stream.on('data', function(chunk) {
    str += chunk;
  });
  stream.on('end', function() {
    callback(str);
  });
}

// how to use:
streamToString(myStream, function(myStr) {
  console.log(myStr);
});
6
flori

人気のある(毎週500万回以上のダウンロード)および軽量なget-streamライブラリを使用した簡単な方法:

https://www.npmjs.com/package/get-stream

const fs = require('fs');
const getStream = require('get-stream');

(async () => {
    const stream = fs.createReadStream('Unicorn.txt');
    console.log(await getStream(stream)); //output is string
})();
4
Ville

私はそのようなものを使用してより多くの運がありました:

let string = '';
readstream
    .on('data', (buf) => string += buf.toString())
    .on('end', () => console.log(string));

ノードv9.11.1を使用し、readstreamhttp.getコールバックからの応答です。

3
vdegenne

ストリームリデューサーのようなものはどうですか?

ES6クラスを使用する方法の例を次に示します。

var stream = require('stream')

class StreamReducer extends stream.Writable {
  constructor(chunkReducer, initialvalue, cb) {
    super();
    this.reducer = chunkReducer;
    this.accumulator = initialvalue;
    this.cb = cb;
  }
  _write(chunk, enc, next) {
    this.accumulator = this.reducer(this.accumulator, chunk);
    next();
  }
  end() {
    this.cb(null, this.accumulator)
  }
}

// just a test stream
class EmitterStream extends stream.Readable {
  constructor(chunks) {
    super();
    this.chunks = chunks;
  }
  _read() {
    this.chunks.forEach(function (chunk) { 
        this.Push(chunk);
    }.bind(this));
    this.Push(null);
  }
}

// just transform the strings into buffer as we would get from fs stream or http request stream
(new EmitterStream(
  ["hello ", "world !"]
  .map(function(str) {
     return Buffer.from(str, 'utf8');
  })
)).pipe(new StreamReducer(
  function (acc, v) {
    acc.Push(v);
    return acc;
  },
  [],
  function(err, chunks) {
    console.log(Buffer.concat(chunks).toString('utf8'));
  })
);
2
Fred

最もクリーンなソリューションは、「string-stream」パッケージを使用することです。これは、ストリームを約束のあるストリングに変換します。

const streamString = require('stream-string')

streamString(myStream).then(string_variable => {
    // myStream was converted to a string, and that string is stored in string_variable
    console.log(string_variable)

}).catch(err => {
     // myStream emitted an error event (err), so the promise from stream-string was rejected
    throw err
})
2
Steve Breese

setEncoding( 'utf8');

上記のセバスチャンJ.

数行のテストコードで「バッファの問題」が発生し、エンコード情報を追加して解決しました。以下を参照してください。

問題を実証する

ソフトウェア

// process.stdin.setEncoding('utf8');
process.stdin.on('data', (data) => {
    console.log(typeof(data), data);
});

入力

hello world

出力

object <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64 0d 0a>

ソリューションのデモ

ソフトウェア

process.stdin.setEncoding('utf8'); // <- Activate!
process.stdin.on('data', (data) => {
    console.log(typeof(data), data);
});

入力

hello world

出力

string hello world
1
Ivan

非常に人気のあるstream-buffersパッケージ を使用すると、おそらく既にプロジェクトの依存関係に含まれているため、これは非常に簡単です。

// imports
const { WritableStreamBuffer } = require('stream-buffers');
const { promisify } = require('util');
const { createReadStream } = require('fs');
const pipeline = promisify(require('stream').pipeline);

// sample stream
let stream = createReadStream('/etc/hosts');

// pipeline the stream into a buffer, and print the contents when done
let buf = new WritableStreamBuffer();
pipeline(stream, buf).then(() => console.log(buf.getContents().toString()));
0
andrewdotn

これは私のために働いており、 Node v6.7.0 docs に基づいています:

let output = '';
stream.on('readable', function() {
    let read = stream.read();
    if (read !== null) {
        // New stream data is available
        output += read.toString();
    } else {
        // Stream is now finished when read is null.
        // You can callback here e.g.:
        callback(null, output);
    }
});

stream.on('error', function(err) {
  callback(err, null);
})
0
anthonygore