4

使用 Chrome,我正在尝试读取和处理本地磁盘上的一个大 (>4GB) 二进制文件。看起来 FileReader API 只会读取整个文件,但我需要能够以流的形式逐步读取文件。

该文件包含一个帧序列,其中包含一个 1 字节类型标识符、一个 2 字节帧长度、一个 8 字节时间戳,然后是一些具有基于类型的格式的二进制数据。这些帧的内容会被累积起来,我想用HTML5+JavaScript来生成图表,并根据这个文件的内容实时回放显示其他指标。

有人有什么想法吗?

4

1 回答 1

7

实际上,Files 是 Blob,并且 Blob 有一个 slice 方法,我们可以使用它来抓取更小的大文件块。

我上周编写了以下片段来过滤大型日志文件,但它显示了您可以用来在大文件中逐个子节循环的模式。

  1. 文件是文件对象
  2. fnLineFilter 是一个函数,它接受文件的一行并返回 true 以保留它
  3. fnComplete 是一个回调,其中收集的行作为数组传递

这是我使用的代码:

 function fileFilter(file, fnLineFilter, fnComplete) {
     var bPos = 0,
         mx = file.size,
         BUFF_SIZE = 262144,
         i = 0,
         collection = [],
         lineCount = 0;
     var d1 = +new Date;
     var remainder = "";

     function grabNextChunk() {

         var myBlob = file.slice(BUFF_SIZE * i, (BUFF_SIZE * i) + BUFF_SIZE, file.type);
         i++;

         var fr = new FileReader();

         fr.onload = function(e) {

             //run line filter:
             var str = remainder + e.target.result,
                 o = str,
                 r = str.split(/\r?\n/);
             remainder = r.slice(-1)[0];
             r.pop();
             lineCount += r.length;

             var rez = r.map(fnLineFilter).filter(Boolean);
             if (rez.length) {
                 [].push.apply(collection, rez);
             } /* end if */

             if ((BUFF_SIZE * i) > mx) {
                 fnComplete(collection);
                 console.log("filtered " + file.name + " in " + (+new Date() - d1) + "ms  ");
             } /* end if((BUFF_SIZE * i) > mx) */
             else {
                 setTimeout(grabNextChunk, 0);
             }

         };
         fr.readAsText(myBlob, myBlob.type);
     } /* end grabNextChunk() */

     grabNextChunk();
 } /* end fileFilter() */

显然,您可以摆脱寻线,而只获取纯范围;我不确定你需要挖掘什么类型的数据,重要的是切片机制,上面以文本为中心的代码很好地证明了这一点。

于 2013-06-20T20:41:59.413 回答