html5 fileReader — how to only read the first N ch

2019-02-11 23:51发布

Currently I use a pattern like the following to read the first 3 characters of a series of files:

var files = e.dataTransfer.files;
for (var i = 0, f; f = files[i]; i++) {
  var fr = new FileReader();
  fr.onload = function(e) { 
    var first_three_chars = e.target.result.substr(0,3);
  }
  fr.readAsText(f);
}

The trouble is that I'm only interested in the first 3 characters of the file, whereas this method reads the entire file, wasting lots of memory and time. How can I quickly iterate over the files, simply taking quick peeks at the first characters?

Edit: slice() was the answer, thanks sshen. Here's how I did it:

var files = e.dataTransfer.files;
for (var i = 0, f; f = files[i]; i++) {
  var fr = new FileReader();
   fr.onloadend = function(e) {
    if (e.target.readyState == FileReader.DONE) {
      var first_three_chars = e.target.result;
    }
  };
  var blob = f.slice(0, 3);
  fr.readAsText(blob);
}

3条回答
SAY GOODBYE
2楼-- · 2019-02-12 00:13

Not enough rep to comment, so putting some warnings about @Stu Blair solution here: With the Blob.slice method you are taking the bytes from the Blob, not the characters.

For example, this won't work:

const blob = new Blob(['                                                                    
查看更多
\"骚年 ilove
3楼-- · 2019-02-12 00:17

Either way you still have to go through the list of files, the contents of the FileList interface. The reason you're reading in the entire file is when you attach onload to every file and call readAsText() If you don't want to read in the entire file, just register an event handler that gets called back with the filelist before the files are loaded and goes through it. Something like this, where you attach to a form submission or something that expects to get the file list as part of its event object, without reading each one first.

<input type="file" id="files" name="files[]" multiple />
<output id="list"></output>

<script>
  function handleFileSelect(evt) {
    var files = evt.target.files; // FileList object

    // files is a FileList of File objects. List some properties.
    var output = [];
    for (var i = 0, f; f = files[i]; i++) {
      var fileName = f.name.substr(0,3);
      output.push('<strong>', fileName, '</strong>');
    }
    document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
  }

  document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>
查看更多
够拽才男人
4楼-- · 2019-02-12 00:22

You can use the .slice method. You can read more here

var reader = new FileReader();

reader.onloadend = function(evt) 
{
    if (evt.target.readyState == FileReader.DONE)  // DONE == 2
    {
        alert(evt.target.result);
    }
};

var blob = file.slice(start, stop + 1);
reader.readAsBinaryString(blob);
查看更多
登录 后发表回答