2014-09-12 19 views
24

Meine Dateileser api-Code wurde, bis eines Tages so weit gute Arbeit habe ich eine 280MB txt-Datei von einem meiner Kunden. Seite stürzt gerade in Chrome ab und in Firefox passiert nichts.Filereader api auf große Dateien

Was ich oben zu tun versuche ist, dass die erste Zeile zu brechen, so dass ich die Spaltenlänge der Datei erhalten kann. Sollte ich es nicht als Text lesen? Wie kann ich die Spaltenlänge der Datei erhalten, ohne die Seite bei großen Dateien zu unterbrechen?

Antwort

46

Ihre Anwendung schlägt bei großen Dateien fehl, weil Sie die gesamte Datei vor der Verarbeitung im Speicher lesen. Diese Ineffizienz kann durch Streaming der Datei (Lesen von Chunks einer kleinen Größe) gelöst werden, so dass Sie nur einen Teil der Datei im Speicher halten müssen.

Eine File Objekte ist auch eine Instanz von Blob, die die .slice Methode bietet, um eine kleinere Ansicht der Datei zu erstellen.

Hier ist ein Beispiel, das davon ausgeht, dass die Eingabe ASCII ist (demo: http://jsfiddle.net/mw99v8d4/).

function findColumnLength(file, callback) { 
    // 1 KB at a time, because we expect that the column will probably small. 
    var CHUNK_SIZE = 1024; 
    var offset = 0; 
    var fr = new FileReader(); 
    fr.onload = function() { 
     var view = new Uint8Array(fr.result); 
     for (var i = 0; i < view.length; ++i) { 
      if (view[i] === 10 || view[i] === 13) { 
       // \n = 10 and \r = 13 
       // column length = offset + position of \r or \n 
       callback(offset + i); 
       return; 
      } 
     } 
     // \r or \n not found, continue seeking. 
     offset += CHUNK_SIZE; 
     seek(); 
    }; 
    fr.onerror = function() { 
     // Cannot read file... Do something, e.g. assume column size = 0. 
     callback(0); 
    }; 
    seek(); 

    function seek() { 
     if (offset >= file.size) { 
      // No \r or \n found. The column size is equal to the full 
      // file size 
      callback(file.size); 
      return; 
     } 
     var slice = file.slice(offset, offset + CHUNK_SIZE); 
     fr.readAsArrayBuffer(slice); 
    } 
} 

Das vorherige Snippet zählt die Anzahl der Bytes vor einem Zeilenumbruch. Das Zählen der Anzahl der Zeichen in einem Text, der aus Multibyte-Zeichen besteht, ist etwas schwieriger, weil Sie die Möglichkeit berücksichtigen müssen, dass das letzte Byte im Chunk Teil eines Multibyte-Zeichens sein könnte.

+2

Sie sind offiziell mein Held. Zuerst hatte ich die gleiche Idee, es als Klumpen zu lesen, anstatt das Ganze zu lesen, aber ich wusste nicht genug, um es zum Laufen zu bringen. Du hast keine Ahnung, wie sehr ich das schätze. Vielen Dank! – ODelibalta

+0

Was würden Sie empfehlen, wenn ich den letzten Teil in der Datei ermitteln muss? Das System, mit dem ich arbeite, hat eine andere REST-API für den letzten Teil, der dann die gesamte Datei festschreibt. Aber ich kann mir nicht vorstellen, wie ich das letzte Stück bestimmen soll. Wenn Sie nicht auf meine Frage suchen würde daran, dass wäre hilfreich http://stackoverflow.com/questions/39312451/determining-the-last-file-chunk/39312577#39312577 – Batman

+1

Ich frage mich, wie ich diese verwenden können, um [ lesen 'n' Zeilen aus einer großen Datei] (http://stackoverflow.com/questions/39479090/read-n-lines-of-a-big-text-file) .....:/ – gsamaras