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

Ric*_*Ric 4 javascript mozilla firefox-addon

我正在尝试使用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);
    });
}
Run Code Online (Sandbox Code Playgroud)

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

nma*_*ier 5

您已charset在选项中指定了显式NetUtil.readInputStream.

省略该charset选项时,数据将作为原始字节读取.(来源)

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);
    });
}
Run Code Online (Sandbox Code Playgroud)

使用的建议io/byte-streams也没关系,但请记住,SDK模块仍然标记为实验性,并且使用ByteReadervia 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);
    });
}
Run Code Online (Sandbox Code Playgroud)

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

  • 该文件首先作为char(字节)数组读取,因此在流中至少有一个临时缓冲区file.size(via 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)中,这样可以比字符串更有效地存储字节数组,并避免使用NetUtil.readInputStreamToString和/或临时缓冲区ByteReader.

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);
    });
}
Run Code Online (Sandbox Code Playgroud)

PS:如果调用中charset省略了该选项,MDN文档可能会声明"iso-8859-1"是默认值NetUtil.readInputStreamToString,但文档错误.我会解决它.