在 JavaScript 中逐步读取二进制文件

Kru*_*rum 4 html javascript google-chrome large-files

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

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

有人有任何想法吗?

dan*_*vis 7

实际上,文件就是 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() */
Run Code Online (Sandbox Code Playgroud)

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