如何通过块(2kb或更多)在本地读取任何大文件(大于1千兆字节),然后将块转换为字符串,处理字符串然后获取下一个块,依此类推,直到结束文件?
我只能读取小文件并将其转换为字符串,您可以从代码中看到我不知道如何通过块读取文件。如果我尝试使用大于10mb的文件,浏览器会冻结。
<html>
<head>
<title>Read File</title>
</head>
<body>
<input type="file" id="myFile">
<hr>
<textarea style="width:500px;height: 400px" id="output"></textarea>
<script>
var input = document.getElementById("myFile");
var output = document.getElementById("output");
input.addEventListener("change", function () {
if (this.files && this.files[0]) {
var myFile = this.files[0];
var reader = new FileReader();
reader.addEventListener('load', function (e) {
output.textContent = e.target.result;
});
reader.readAsBinaryString(myFile);
}
});
</script>
</body>
</html>
以下是我在StackOverflow上发现的链接和答案,同时研究如何完成它,但它并没有解决我的问题。
1:这个问题是询问如何使用UniversalXPConnect进行,只有在Firefox中,这就是为什么我发现那里的答案无关紧要,因为我使用的是Chrome并且不在知道UniversalXPConnect是什么。 How to read a local file by chunks in JavaScript
2:这个问题只是询问如何阅读文本文件,但我希望能够读取任何文件,不仅仅是文本,也可以读取块,这使得答案无关紧要,但我喜欢答案的代码有多短。 Reading local text file into a JavaScript array [duplicate]
3:这也是关于文本文件的,并没有显示如何按块How to read a local text file.
读取文件
我知道一点Java,你可以很容易地做到这一点;
char[] myBuffer = new char[512];
int bytesRead = 0;
BufferedReader in = new BufferedReader(new FileReader("foo.mp4"));
while ((bytesRead = in.read(myBuffer,0,512)) != -1){
...
}
但我是javascript新手
答案 0 :(得分:0)
所以问题不在于FileReader
,而在于:
output.textContent = e.target.result;
因为您试图一次性将10 MB +的字符串转储到textarea
。我甚至不确定是否有一种“正确”的方式来做你想要的事情,因为即使你确实拥有了它,它仍然必须在每个循环中通过那些汇总output.textContent
的先前值块,所以当它接近结束时,它会以相同的方式开始减速(更糟糕的是,真的,因为它会在每个循环上做慢速内存占用业务)。所以我认为部分循环过程必须添加一个新元素(比如新的textarea
来推送当前的块(因此它不需要进行任何连接来保留已经存在的内容)我还没有完成那部分工作,但到目前为止我已经完成了这件事:
var input = document.getElementById("myFile");
var output = document.getElementById("output");
var chunk_length = 2048; //2KB as you mentioned
var chunker = new RegExp('[^]{1,' + chunk_length + '}', 'g');
var chunked_results;
input.addEventListener("change", function () {
if (this.files && this.files[0]) {
var myFile = this.files[0];
var reader = new FileReader();
reader.addEventListener('load', function (e) {
chunked_results = e.target.result.match(chunker);
output.textContent = chunked_results[0];
});
reader.readAsBinaryString(myFile);
}
});
这只是输出2KB块数组中的第一个字符串。你想做的就是在DOM文档中添加一个新的元素/节点来输出所有其他的块。
使用RegExp
和match
进行实际分块是从我找到的clever gist中解除的。
答案 1 :(得分:0)
我能够通过指定文件的切片来解决它,通过指定切片的开始位置以及将要结束的块的位置,然后将其包含在while循环中,以便每个循环块位置将根据到文件末尾所需的块大小。
但是在运行之后,我最终得到了文本区域中块的最后一个值,所以要显示所有二进制字符串,我会在每次迭代时连接输出。
<html>
<head>
<title>Read File</title>
</head>
<body>
<input type="file" id="myFile">
<hr>
<textarea style="width:500px;height: 400px" id="output"></textarea>
<script>
var input = document.getElementById("myFile");
var output = document.getElementById("output");
var chunk_size = 2048;
var offset = 0;
input.addEventListener("change", function () {
if (this.files && this.files[0]) {
var myFile = this.files[0];
var size = myFile.size; //getting the file size so that we can use it for loop statement
var i=0;
while( i<size){
var blob = myFile.slice(offset, offset + chunk_size); //slice the file by specifying the index(chunk size)
var reader = new FileReader();
reader.addEventListener('load', function (e) {
output.textContent += e.target.result; //concatenate the output on each iteration.
});
reader.readAsBinaryString(blob);
offset += chunk_size; // Increment the index position(chunk)
i += chunk_size; // Keeping track of when to exit, by incrementing till we reach file size(end of file).
}
}
});
</script>
</body>
</html>
答案 2 :(得分:-1)
您可以使用fs.createReadStream()执行此操作,可能缓冲的数据量取决于传递给流构造函数的highWaterMark选项。 所以你会这样做:
var read = fs.createReadStream(&#39; / something / something&#39;,{highWaterMark:64});
这是一个例子:
var fs = require('fs')
var read = fs.createReadStream('readfile.txt',{highWaterMark:64})
var write = fs.createWriteStream('written.txt')
read.on('open', function () {
read.pipe(write);
});
看看它一次读取64个字节(非常慢),你可以用有趣的方式在资源管理器上查看它,但要确保你有一个大文本文件来测试它不是一个千兆字节,但至少有17兆字节像我一样做了#34;填写任何虚拟文本&#34; 将文件视图设为&#34;详细信息&#34;并在Windows资源管理器中不断刷新目标,每次刷新时都会看到大小增加。
如果你没有问题,我假设你知道管道方法!它非常简单,这里有一个链接: https://nodejs.org/api/stream.html#stream_readable_pipe_destination_options
或快速解释:
readable.pipe(writable)
pipe()函数在可读流可用时读取数据并将其写入目标可写流。