Skip to content

Instantly share code, notes, and snippets.

@NotWoods
Last active December 1, 2022 04:10
Show Gist options
  • Save NotWoods/39e1f7d29a56be0d012461cde409e285 to your computer and use it in GitHub Desktop.
Save NotWoods/39e1f7d29a56be0d012461cde409e285 to your computer and use it in GitHub Desktop.
Node.js - Break up a stream and reassemble it so that each line is a chunk.
const stream = require("stream");
/** Simplified version of split() on npm. */
const split = new stream.Transform({
/**
* @param {Buffer | string} chunk is the data from the Readable Stream.
* @param {string} encoding is the file encoding, but isn't used here.
* @param {() => void} next is a callback function called when you finish working
* with this chunk.
*/
transform(chunk, encoding, next) {
/* this.soFar represents the current line so far.
* First, this.soFar is replaced with "" if it is null or undefined.
* This happens with the first chunk and if Array.pop() is called
* on an empty array.
* Next, the soFar string is combined with the string provided by
* the stream ("chunk"). .toString() converts buffers to strings.
* Finally, the string is split at the newline character defined
* by the \r?\n RegEx. This RegEx translates to either
* "\r\n" or "\n", which are the two end of line characters used by
* Windows and Unix respectively. */
const lines = ((this.soFar != null ? this.soFar: "") + chunk.toString()).split(/\r?\n/);
/* The last element of the array, aka data after the last complete line,
* is removed with Array.pop() and stored in this.soFar for future */
this.soFar = lines.pop();
/* Each complete line is sent as a seperate push. If no line is
* completed, this.push isn't called so nothing is outputted that time. */
for (var line of lines) { this.push(line); }
/* next() indicates that operations on this chunk are done. */
next();
},
/**
* If the file does not end in a newline, flush will output the
* remaining this.soFar data from the last line.
*/
flush(done) {
/* Like the previous instance, this.soFar is
* replaced with "" if it is null or undefined.
* Then, it is pushed out. */
this.push(this.soFar != null ? this.soFar:"");
/* done() indicates that operations are done. */
done();
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment