使用Mozilla附加组件读取原始数据

时间:2014-05-23 04:49:58

标签: javascript firefox-addon mozilla

我尝试使用Mozilla的附加SDK从文件中读取和写入原始数据。目前,我正在使用以下内容读取数据:

function readnsIFile(fileName, callback){
    var nsiFile = new FileUtils.File(fileName);
    NetUtil.asyncFetch(nsiFile, function (inputStream, status) {
        var data = NetUtil.readInputStreamToString(inputStream, inputStream.available(),{charset:"UTF-8"});
        callback(data, status, nsiFile);
    });
}

这适用于文本文件,但是当我开始处理Unicode正常范围之外的原始字节时,它不起作用。例如,如果文件包含字节0xff,则该字节和该字节之外的任何内容都不会被读取。有没有办法使用SDK读取(和写入)原始数据?

1 个答案:

答案 0 :(得分:5)

您已在charset的选项中指定了明确的NetUtil.readInputStream

当省略charset选项时,数据将被读取为原始字节。 (Source

function readnsIFile(fileName, callback){
    var nsiFile = new FileUtils.File(fileName);
    NetUtil.asyncFetch(nsiFile, function (inputStream, status) {
        // Do not specify a charset at all!
        var data = NetUtil.readInputStreamToString(inputStream, inputStream.available());
        callback(data, status, nsiFile);
    });
}

使用io/byte-streams的建议也可以,但请记住,该SDK模块仍然标记为实验性的,并且使用ByteReader通过io/file作为示例建议不是一个好主意,因为这将是主线程上的同步I / O. 我不会真正看到好处,因为你无论如何都会使用NetUtil

无论如何,这应该有效:

const {ByteReader} = require("sdk/io/byte-streams");
function readnsIFile(fileName, callback){
    var nsiFile = new FileUtils.File(fileName);
    NetUtil.asyncFetch(nsiFile, function (inputStream, status) {
        var reader = new ByteReader(inputStream);
        var data = reader.read(inputStream);
        reader.close();
        callback(data, status, nsiFile);
    });
}

此外,请记住,阅读像这样的大文件是有问题的。显然,不仅整个文件都会缓存在内存中,而且:

  • 首先将文件读作char(字节)数组,因此流中至少有file.size长度的临时缓冲区(通过asyncFetch)。
  • NetUtil.readInputStreamToStringByteReader都会使用另一个char(字节)数组从inputStream读取结果,但ByteReader会在32K块(NetUtil.readInputStreamToString)将使用file.length的大缓冲区。
  • 然后将数据读入生成的jschar / wchar_t(单词)数组中。 Javascript字符串,即至少在内存中需要file.size * 2个字节。

例如,读取1MB文件需要超过fileSize * 4 = 4MB内存(NetUtil.readInputStreamToString)和/或超过fileSize * 3 = 3MB内存(ByteReader)读操作。在操作之后,2MB的内存仍然存活,以将结果数据存储在Javascript字符串中。

读取1MB文件可能没问题,但是10MB文件可能已经在移动设备上出现问题(适用于Android的Firefox,Firefox OS),即使在桌面设备上也会出现100MB的问题。

您还可以直接将数据读入ArrayBuffer(或Uint8Array),这对于字节数组的存储比Javascript字符串更有效,并避免NetUtil.readInputStreamToStringByteReader的临时缓冲区/或function readnsIFile(fileName, callback){ var nsiFile = new FileUtils.File(fileName); NetUtil.asyncFetch(nsiFile, function (inputStream, status) { var bs = Cc["@mozilla.org/binaryinputstream;1"]. createInstance(Ci.nsIBinaryInputStream); bs.setInputStream(inputStream); var len = inputStream.available(); var data = new Uint8Array(len); reader.readArrayBuffer(len, data.buffer); bs.close(); callback(data, status, nsiFile); }); }

charset

PS:MDN文档可能会说明" iso-8859-1"如果在NetUtil.readInputStreamToString调用中省略{{1}}选项,则为默认值,但文档错误。我会解决它。