How to learn nsIZipWriter and nsIZipReader? [close

2019-09-05 20:10发布

I was wondering how to use JavaScript to do async zip writing and reading.

1条回答
可以哭但决不认输i
2楼-- · 2019-09-05 20:47

Here is an example for zip reading using nsIZipReader, zip writing goes in a similar way. The example reads a zip file from /tmp/example.zip and prints the content of the first file to the console.

Remarks:

  • I'm using nsIInputStreamPump for async I/O I found a reference to this API at the Streams guide on MDN. This interface offers a .asyncRead method which takes an object that implements nsIStreamListener (and nsIRequestObserver).
  • I have compared the running time of this example with the synchronous zip reading example at MDN and found that reading the time used by the blocking read is significantly smaller (reading a zip file from RAM disk: from 1-2ms to 0.1-0.3ms) (measured using console.time('foo'); before the reusableStreamInstance.init invocation and console.timeEnd('foo'); after reusableStreamInstance.readBytes).
  • I am using .readBytes instead of .read to avoid truncation of data if the file contains a null byte.
  • I haven't implemented any error handling (zip not existent, zip doesn't contain a file, zip/file cannot be opened), but I do close the zipreader regardless of whether an error occurs.
let { Cc: classes, Cu: utils, Ci: interfaces } = Components;

Cu.import('resource://gre/modules/FileUtils.jsm');

let pathToZip = '/tmp/example.zip';
let nsiFileZip = new FileUtils.File(pathToZip);

let streamListener = {
  buffer: null,
  // nsIRequestObserver
  onStartRequest: function(aRequest, aContext) {
    this.buffer = [];
  },
  // nsIStreamListener
  onDataAvailable:
      function(aRequest, aContext, aInputStream, aOffset, aCount) {
    let reusableStreamInstance = Cc['@mozilla.org/scriptableinputstream;1']
        .createInstance(Ci.nsIScriptableInputStream);
    reusableStreamInstance.init(aInputStream);
    let chunk = reusableStreamInstance.readBytes(aCount);
    this.buffer.push(chunk);
  },
  // nsIRequestObserver
  onStopRequest: function(aRequest, aContext, aStatusCode) {
    console.log('end', aStatusCode);
    var data = this.buffer.join('');
    console.log(data);
  }
};

let pump = Cc['@mozilla.org/network/input-stream-pump;1']
    .createInstance(Ci.nsIInputStreamPump);
let zr = Cc['@mozilla.org/libjar/zip-reader;1']
    .createInstance(Ci.nsIZipReader);
try {
  zr.open(nsiFileZip);
  // null = no entry name filter.
  var entries = zr.findEntries(null);
  while (entries.hasMore()) {
    var entryPointer = entries.getNext();
    var entry = zr.getEntry(entryPointer);
    if (!entry.isDirectory) {
      var stream = zr.getInputStream(entryPointer);
      pump.init(stream, 0, -1, 0, 0, true);
      pump.asyncRead(streamListener, null);
      // For the demo, we only take one file, so break now.
      break;
    }
  }
} finally {
  zr.close();
}
查看更多
登录 后发表回答