Skip to content

Instantly share code, notes, and snippets.

@shuhei
Last active January 23, 2017 08:51
Show Gist options
  • Save shuhei/0b24f90d7bd8891ddd42c46188868bf8 to your computer and use it in GitHub Desktop.
Save shuhei/0b24f90d7bd8891ddd42c46188868bf8 to your computer and use it in GitHub Desktop.
Gunzip multiple gzip chunks

Gunzip multiple gzip chunks

https://twitter.com/yteraoka/status/823398592635252736

Test

echo 123 | gzip > a.gz
echo 456 | gzip >> a.gz

npm install stream-stream
cat a.gz | node index.js

cat a.gz | node simple.js

TODO

  • Handle magic bytes properly
  • Check if stream-stream's implementation is fare enough
  • Check more edge cases
const stream = require('stream');
const zlib = require('zlib');
const ss = require('stream-stream');
// A tranform stream that reads a buffer stream and writes gunzip streams
class MultiGunzip extends stream.Transform {
constructor() {
super({ objectMode: true });
}
_transform(chunk, encoding, callback) {
const len = chunk.byteLength;
let start = 0;
for (let i = 0; i < len - 1; i += 1) {
// Magic bytes
if (chunk[i] === 31 && chunk[i + 1] === 139) {
if (this.gunzip) {
this.gunzip.end(chunk.slice(start, i));
}
this.gunzip = zlib.createGunzip();
start = i;
this.push(this.gunzip);
}
}
// TODO: Check whether the last byte is the first of magic bytes.
this.gunzip.write(chunk.slice(start));
callback(null);
}
_flush(callback) {
callback(null);
}
}
const multi = new MultiGunzip();
process.stdin.pipe(multi).pipe(ss()).pipe(process.stdout);
process.stdin.pipe(require('zlib').createGunzip()).pipe(process.stdout);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment