提问人:kacase 提问时间:2/17/2021 最后编辑:Mark Schultheisskacase 更新时间:10/27/2023 访问量:1654
JavaScript FileReader Slice 性能
JavaScript FileReader Slice Performance
问:
我正在尝试使用 JavaScript 访问文本文件的前几行。FileApi
为此,我从文件开头切片任意数量的字节,并将 blob 移交给 .FileReader
对于大文件,这需要很长时间,尽管我目前的理解是只需要访问文件的前几个字节。
- 后台是否有一些实现需要先访问整个文件,然后才能对其进行切片?
- 它是否取决于 FileApi 的浏览器实现?
我目前已经在 Chrome 和 Edge (chromium) 中进行了测试。
使用性能开发工具在 Chrome 中的分析显示,在 Chrome 之前有大量空闲时间,并且 ram 使用率没有增加。但是,这可能是因为 是在浏览器本身中实现的,并且不会反映在 JavaScript 性能统计信息中。reader.onloadend
FileApi
我的 FileReader 实现如下所示:
const reader = new FileReader();
reader.onloadend = (evt) => {
if (evt.target.readyState == FileReader.DONE) {
console.log(evt.target.result.toString());
}
};
// Slice first 10240 bytes of the file
var blob = files.item(0).slice(0, 1024 * 10);
// Start reading the sliced blob
reader.readAsBinaryString(blob);
这工作正常,但如前所述,对于大文件的表现相当糟糕。我尝试了 10kb、100mb 和 6gb。记录前 10kb 的时间似乎与文件大小直接相关。
关于如何提高读取文件开头的性能的任何建议?
编辑: 遗憾的是,按照@BenjaminGruenbaum的建议使用 Response 和 DOM 流并不能提高读取性能。
var dest = newWritableStream({
write(str) {
console.log(str);
},
});
var blob = files.item(0).slice(0, 1024 * 10);
(blob.stream ? blob.stream() : newResponse(blob).body)
// Decode the binary-encoded response to string
.pipeThrough(newTextDecoderStream())
.pipeTo(dest)
.then(() => {
console.log('done');
});
答:
这个怎么样!!
function readFirstBytes(file, n) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
resolve(reader.result);
};
reader.onerror = reject;
reader.readAsArrayBuffer(file.slice(0, n));
});
}
readFirstBytes('file', 10).then(buffer => {
console.log(buffer);
});
评论
只是为了踢球,这里有一个工作线程和文件系统访问 API
不知道这些东西是否有帮助,我没有 6gb 文件。 这将使读数脱离主线程,因此在某种意义上确实有助于性能。
Object.assign(
new Worker(
URL.createObjectURL(
new Blob(
[
`self.onmessage = async (e) =>` +
` void postMessage(` +
` (new FileReaderSync())` +
` .readAsText(` +
` (await e.data.getFile())` +
` .slice(0,1024*10)` +
` )` +
` );`
],
{ type: 'application/javascript' }
)
)
),
{ onmessage: (e) => void console.log(e.data) }
).postMessage(
(await window.showOpenFilePicker(
{ mode: 'read', startIn: 'documents' }
)).pop()
);
编辑:
forgor,但你需要铬来做这个 rn 对不起(在 Edge 上测试) 此外,这不会在 jsfiddle 中运行,因为 Web Worker 等等,安全性等等。不过,您可以将其复制粘贴到Google上的控制台中。出于某种原因,标头不会阻止 Thins 运行。如果这确实有帮助,请把工人放在自己的文件中(并重新格式化我的艺术负空间三角形)
我认为在你的情况下,要获取文件浏览器的切片,仍然必须读取整个文件才能从原始文件创建切片
可能订阅该事件可以帮助更快地访问文件内容,然后中止读取过程progress
reader.addEventListener("progress", (event) => {});
Blob 接口的 slice() 方法创建并返回一个新的 Blob 对象,该对象包含来自调用它的 blob 子集的数据。
我们可以从 chrome README for Blob 类中获得相同的结论
我在下面没有看到任何延迟运行代码。(dmg 文件大小为 ~220MB)
试试自己。
评论
响应
和 DOM 流有帮助吗?我不确定为什么这里很慢,因为在 blob 上使用应该只读取您想要的部分 - 但是您描述的内容表明它确实在等待整个文件。readAsBinarySring
.slice