development

Node.js 스트림의 내용을 문자열 변수로 어떻게 읽습니까?

big-blog 2020. 10. 20. 07:48
반응형

Node.js 스트림의 내용을 문자열 변수로 어떻게 읽습니까?


smtp-protocolSMTP 이메일을 캡처하고 메일 데이터를 처리 하는 데 사용하는 Node 프로그램을 해킹하고 있습니다. 라이브러리는 메일 데이터를 스트림으로 제공하며 문자열로 가져 오는 방법을 모르겠습니다.

나는 현재 그것을 stdout에 쓰고 stream.pipe(process.stdout, { end: false })있지만 말했듯이 스트림 데이터가 대신 문자열로 필요하며 스트림이 끝나면 사용할 수 있습니다.

Node.js 스트림의 모든 데이터를 문자열로 수집하려면 어떻게해야합니까?


핵심은 Readable Streamdataend이벤트 를 사용하는 것 입니다. 다음 이벤트를 들어보십시오.

stream.on('data', (chunk) => { ... });
stream.on('end', () => { ... });

data이벤트 를 수신하면 데이터를 수집하기 위해 생성 된 버퍼에 새 데이터 청크를 추가합니다.

end이벤트 를 받으면 필요한 경우 완료된 버퍼를 문자열로 변환합니다. 그런 다음 필요한 작업을 수행하십시오.


위의 답변보다 유용하기를 바랍니다.

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

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

문자열 연결은 문자열 부분을 수집하는 가장 효율적인 방법은 아니지만 단순성을 위해 사용됩니다 (그리고 코드가 효율성에 관심이 없을 수도 있음).

또한이 코드는 비 ASCII 텍스트에 대해 예측할 수없는 오류를 생성 할 수 있지만 (모든 문자가 한 바이트에 맞는다고 가정 함) 아마도 당신은 그것에 대해 신경 쓰지 않을 것입니다.


위의 어느 것도 나를 위해 일하지 않았습니다. 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));
  });

또 다른 방법은 스트림을 promise로 변환하고 (아래 예제 참조) 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)

일반적으로이 간단한 함수를 사용하여 스트림을 문자열로 변환합니다.

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

nodejs 문서 에서이 작업을 수행해야합니다. 인코딩이 단지 한 무리의 바이트라는 것을 알지 못한 채 문자열을 항상 기억하십시오.

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

스트림에는 .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);
});

나는 다음과 같이 더 많은 행운을 얻었습니다.

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

나는 노드를 사용 v9.11.1하고는 readstreama로부터 반응이다 http.get콜백.


인기있는 (주간 다운로드 5 백만 회 이상) 가벼운 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
})();

스트림 감속기와 같은 것은 어떻습니까?

다음은 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'));
  })
);

The cleanest solution may be to use the "string-stream" package, which converts a stream to a string with a promise.

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
})

This worked for me and is based on 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);
})

setEncoding('utf8');

Well done Sebastian J above.

I had the "buffer problem" with a few lines of test code I had, and added the encoding information and it solved it, see below.

Demonstrate the problem

software

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

input

hello world

output

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

Demonstrate the solution

software

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

input

hello world

output

string hello world

Using the quite popular stream-buffers package which you probably already have in your project dependencies, this is pretty straightforward:

// 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()));

And yet another one for strings using promises:

function getStream(stream) {
  return new Promise(resolve => {
    const chunks = [];

    stream.on("data", chunk => chunks.push(chunk));
    stream.on("end", () => resolve(Buffer.concat(chunks).toString()));
  });
}

Usage:

const stream = fs.createReadStream(__filename);
getStream(stream).then(r=>console.log(r));

remove the .toString() to use with binary Data if required.

참고URL : https://stackoverflow.com/questions/10623798/how-do-i-read-the-contents-of-a-node-js-stream-into-a-string-variable

반응형