我尝试使用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读取(和写入)原始数据?
答案 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.readInputStreamToString
和ByteReader
都会使用另一个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.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);
});
}
。
charset
PS:MDN文档可能会说明" iso-8859-1"如果在NetUtil.readInputStreamToString
调用中省略{{1}}选项,则为默认值,但文档错误。我会解决它。