2015-01-13 14 views
6

Ho bisogno di aiuto per capire come si accede al file in JavaScript per fare alcune operazioni su di esso.Come faccio a scorrere un file, byte per byte, in JavaScript?

Vorrei scorrere un file byte per byte utilizzando JavaScript. Posso già selezionare il file che vorrei leggere. E posso leggere il byte preimpostato del file.

ho trovato questo bell'esempio su come leggere una fetta di un file qui:

http://www.html5rocks.com/en/tutorials/file/dndfiles/

Ecco il frammento di codice che sto giocando con:

<style> 
    #byte_content { 
    margin: 5px 0; 
    max-height: 100px; 
    overflow-y: auto; 
    overflow-x: hidden; 
    } 
    #byte_range { margin-top: 5px; } 
</style> 

<input type="file" id="files" name="file" /> Read bytes: 
<span class="readBytesButtons"> 
    <button data-startbyte="0" data-endbyte="4">1-5</button> 
    <button data-startbyte="5" data-endbyte="14">6-15</button> 
    <button data-startbyte="6" data-endbyte="7">7-8</button> 
    <button>entire file</button> 
</span> 
<div id="byte_range"></div> 
<div id="byte_content"></div> 

<script> 
    function readBlob(opt_startByte, opt_stopByte) { 

    var files = document.getElementById('files').files; 
    if (!files.length) { 
     alert('Please select a file!'); 
     return; 
    } 

    var file = files[0]; 
    var start = parseInt(opt_startByte) || 0; 
    var stop = parseInt(opt_stopByte) || file.size - 1; 

    var reader = new FileReader(); 

    // If we use onloadend, we need to check the readyState. 
    reader.onloadend = function(evt) { 
     if (evt.target.readyState == FileReader.DONE) { // DONE == 2 
     document.getElementById('byte_content').textContent = evt.target.result; 
     document.getElementById('byte_range').textContent = 
      ['Read bytes: ', start + 1, ' - ', stop + 1, 
      ' of ', file.size, ' byte file'].join(''); 
     } 
    }; 

    var blob = file.slice(start, stop + 1); 
    reader.readAsBinaryString(blob); 
    } 

    document.querySelector('.readBytesButtons').addEventListener('click', function(evt) { 
    if (evt.target.tagName.toLowerCase() == 'button') { 
     var startByte = evt.target.getAttribute('data-startbyte'); 
     var endByte = evt.target.getAttribute('data-endbyte'); 
     readBlob(startByte, endByte); 
    } 
    }, false); 
</script> 

Ora vorrei scorrere il file, quattro byte alla volta, ma non riesco a capire come farlo. Il lettore non sembra permettermi di leggere più di una volta.

Una volta che posso leggere dal file più di una volta, dovrei essere in grado di scorrere attraverso di essa abbastanza facilmente con qualcosa di simile:

while(placemark != fileSize-4){ 
    output = file.slice(placemark, placemark + 4);  
    console.log(output); 
    placemark = placemark + 5; 
    } 

Grazie in anticipo! Ecco un link ad un jsFiddle e plnkr versione

+1

Se è possibile, proverei a rifattorizzare il codice di manipolazione DOM dal codice di lettura del file. In questo modo, se hai una chiara separazione delle preoccupazioni, sarà più facile eseguire il debug e apportare modifiche. –

+0

Sono d'accordo! Sento che una volta fatto, il resto dovrebbe essere facile ... Ma non so come? – FredFury

+0

metterlo in un plnkr, quindi dare un'occhiata a refactoring, quindi risolverlo –

risposta

4

io non sono sicuro che è quello che si voleva, ma forse può aiutare, e comunque mi sono divertito.
Ho provato a installare reader e file Vars come globale:

var reader = new FileReader(), step = 4, stop = step, start = 0, file; 
 

 
document.getElementById('files').addEventListener('change', load, true); 
 

 
function load() { 
 
    var files = document.getElementById('files').files; 
 
    file = files[0]; 
 
    reader.onloadend = function(evt) { 
 
    if (evt.target.readyState == FileReader.DONE) { 
 
     var result = evt.target.result; 
 
     document.getElementById('byte_content').textContent += result; 
 
     document.getElementById('byte_range').textContent = ['Read bytes: ', start, ' - ', start+result.length, 
 
     ' of ', file.size, ' byte file' 
 
     ].join(''); 
 
    } 
 
    } 
 
} 
 

 
function next() { 
 
    if (!file) { 
 
    alert('Please select a file!'); 
 
    return; 
 
    } 
 
    var blob = file.slice(start, stop); 
 
    reader.readAsBinaryString(blob); 
 

 
    start+= step; 
 
    stop = start+step; 
 
} 
 

 
function loop() { 
 
    if (!file) { 
 
    alert('Please select a file!'); 
 
    return; 
 
    } 
 
    if (start < file.size) { 
 
    next(); 
 
    setTimeout(loop, 50); 
 
    } 
 
}
<input type="file" id="files" name="file" />Read bytes: 
 
<span class="readBytesButtons"> 
 
    <button onclick="next()">next</button> 
 
    <button onclick="loop()">loop</button> 
 
</span> 
 
<div id="byte_range"></div> 
 
<div id="byte_content"></div>

+0

Brillante. Sì. Funziona benissimo, grazie. Immagino abbia senso che quei vars globali. – FredFury

-2

Nel gestore onload FileReader, convertire il risultato a stringa (toString()), quindi leggere 4 caratteri alla volta con il metodo della stringa slice.

var contents = null; 

reader.onload = function(){ 
    contents = reader.result.toString(); 
} 

var startByte = 0; 

// read 4 bytes at a time 
var step = 4; 

// actual reading (doesn't alter the contents object) 
console.log(contents.slice(startByte, step)) 

// update the next startByte position 
startByte += step; 
+2

4 byte! = 4 caratteri – Justinas

+0

Sì, sarebbe una soluzione carina, se non avessi bisogno dei byte effettivi- Come @Justinas menzionato. Grazie a entrambi, però. – FredFury

1

avevo letto il blob come ArrayBuffer e utilizzare un DataView per leggere i dati

function readBlob(opt_startByte, opt_stopByte) { 
 

 
    var files = document.getElementById('files').files; 
 
    if (!files.length) { 
 
     alert('Please select a file!'); 
 
     return; 
 
    } 
 

 
    var file = files[0]; 
 
    var start = parseInt(opt_startByte) || 0; 
 
    var stop = parseInt(opt_stopByte) || file.size - 1; 
 

 
    var reader = new FileReader(); 
 

 
    reader.onload = function(evt) { 
 
     var placemark = 0, dv = new DataView(this.result), limit = dv.byteLength - 4, output; 
 
     while(placemark <= limit){ 
 
      output = dv.getUint32(placemark);  
 
      console.log(' 0x'+("00000000" + output.toString(16)).slice(-8)); 
 
      placemark += 4; 
 
     }  
 
    }; 
 

 
    var blob = file.slice(start, stop + 1); 
 
    reader.readAsArrayBuffer(blob); 
 
    }
<input type="file" id="files" onchange="readBlob(0, 100)">

+0

Grazie! Questa è sicuramente anche una risposta. – FredFury