Как прочитать любой локальный файл кусками, используя JavaScript? - PullRequest
0 голосов
/ 09 мая 2018

Как я могу прочитать любой большой файл (больше 1 гигабайта) локально по чанкам (2 КБ или более), а затем преобразовать чанк в строку, обработать строку и затем получить следующий чанк и так далее до конца файл?

Я могу читать только небольшие файлы и преобразовывать их в строку, как вы можете видеть из кода, который я не знаю, как читать файл по частям. Браузер зависает, если я попробую его с файлом больше 10 Мб.

<html>
  <head>
    <title>Read File</title>
  </head>

  <body>
    <input type="file" id="myFile">
    <hr>
    <textarea style="width:500px;height: 400px" id="output"></textarea>

    <script>
      var input = document.getElementById("myFile");
      var output = document.getElementById("output");
      input.addEventListener("change", function () {
        if (this.files && this.files[0]) {
          var myFile = this.files[0];
          var reader = new FileReader();
          reader.addEventListener('load', function (e) {
            output.textContent = e.target.result;
          });
          reader.readAsBinaryString(myFile);
        }
      });
    </script>

  </body>
</html>

Ниже приведены ссылки и ответы, которые я нашел в StackOverflow во время исследования того, как этого добиться, но это не решило мой вопрос.

1: Этот вопрос задавался вопросом о том, как это сделать с помощью UniversalXPConnect, и только в Firefox, поэтому я нашел ответ там неуместным, потому что я использую Chrome и не знаю, что UniversalXPConnect есть. Как читать локальный файл кусками в JavaScript

2: Этот вопрос задавался о том, как читать только текстовые файлы, но я хочу иметь возможность читать любой файл не только по тексту, а также по частям, что делает ответы там неуместными, но Мне понравилось, насколько коротким был код ответа. Чтение локального текстового файла в массив JavaScript [дубликат]

3: Это также относится к текстовым файлам и не показывает, как читать файлы по частям Как читать локальный текстовый файл.

Я немного знаю Java, с помощью которого вы можете легко это сделать;

char[] myBuffer = new char[512];
int bytesRead = 0;
BufferedReader in = new BufferedReader(new FileReader("foo.mp4"));
while ((bytesRead = in.read(myBuffer,0,512)) != -1){
...
}

но я новичок в javascript

Ответы [ 3 ]

0 голосов
/ 09 мая 2018

Так что проблема не в FileReader, а в:

output.textContent = e.target.result;

Потому что вы пытаетесь сбросить 10 МБ + строки в этот textarea одновременно. Я даже не уверен, что есть «правильный» способ сделать то, что вы хотите, поскольку, даже если бы у вас это было по частям, ему все равно приходилось бы объединять предыдущее значение output.textContent в каждом цикле через эти куски, так что, когда он приблизится к концу, он начнет замедляться таким же образом (на самом деле, хуже, потому что он будет выполнять медленный захват памяти в каждом цикле). Поэтому я думаю, что частью процесса зацикливания будет добавление нового элемента (например, нового textarea, чтобы выдвинуть текущий фрагмент (чтобы не было необходимости в какой-либо конкатенации для сохранения того, что уже было выведено) Я еще не проработал эту часть, но вот что у меня получилось:

  var input = document.getElementById("myFile");
  var output = document.getElementById("output");
  var chunk_length = 2048; //2KB as you mentioned
  var chunker = new RegExp('[^]{1,' + chunk_length + '}', 'g');
  var chunked_results;

  input.addEventListener("change", function () {
    if (this.files && this.files[0]) {
      var myFile = this.files[0];
      var reader = new FileReader();
      reader.addEventListener('load', function (e) {
        chunked_results = e.target.result.match(chunker);
        output.textContent = chunked_results[0];
      });
      reader.readAsBinaryString(myFile);
    }
  });

Это просто вывод первой строки в массиве кусков по 2 КБ. Вы хотели бы сделать свое дело, добавив новый элемент / узел в документ DOM для вывода всех других кусков.

Использование RegExp и match для фактической порции было снято с умной сущности Я нашел.

0 голосов
/ 09 мая 2018

Я смог решить эту проблему, нарезав файл, указав атрибуты, где начинать срез, а где заканчивать, каким будет чанк, затем я заключил его в цикл while, чтобы для каждой позиции чанка цикла смещаться в соответствии с до нужного размера фрагмента до конца файла.

Но после запуска я получаю последнее значение чанка в текстовой области, поэтому для отображения всей двоичной строки я объединяю выходные данные в каждой итерации.

<html>
<head>
  <title>Read File</title>
</head>

<body>
  <input type="file" id="myFile">
  <hr>
  <textarea style="width:500px;height: 400px" id="output"></textarea>

  <script>
    var input = document.getElementById("myFile");
    var output = document.getElementById("output");
    var chunk_size = 2048;
    var offset = 0;
    input.addEventListener("change", function () {
      if (this.files && this.files[0]) {
        var myFile = this.files[0];
        var size = myFile.size; //getting the file size so that we can use it for loop statement
        var i=0;
        while( i<size){
        var blob = myFile.slice(offset, offset + chunk_size); //slice the file by specifying the index(chunk size)
        var reader = new FileReader();
        reader.addEventListener('load', function (e) {
          output.textContent += e.target.result; //concatenate the output on each iteration.
        });
        reader.readAsBinaryString(blob);
        offset += chunk_size; // Increment the index position(chunk) 
        i += chunk_size; // Keeping track of when to exit, by incrementing till we reach file size(end of file).
        }
      }
    });
  </script>

</body>
</html>
0 голосов
/ 09 мая 2018

Это можно сделать с помощью fs.createReadStream (). Объем потенциально буферизованных данных зависит от параметра highWaterMark, передаваемого в конструктор потоков. Итак, вы бы сделали это так:

var read = fs.createReadStream ('/ что-то / что-то', {highWaterMark: 64});

вот пример:

var fs = require('fs')
var read = fs.createReadStream('readfile.txt',{highWaterMark:64}) 
var write = fs.createWriteStream('written.txt')
read.on('open', function () {
    read.pipe(write);
});

Посмотрите, как он читает 64 байта за раз (очень медленно), вы можете просмотреть его в проводнике в увлекательной игровой форме, но убедитесь, что у вас есть большой текстовый файл, чтобы проверить его не гигабайт, а как минимум 17 мегабайт, как я сделал "заполнить его любым фиктивным текстом" сделайте просмотр файла «подробностями» и продолжайте обновлять место назначения в проводнике Windows, вы увидите увеличение размера при каждом обновлении.

Я предполагаю, что вы знаете о методе трубы, если нет, не проблема! это очень просто, вот ссылка: https://nodejs.org/api/stream.html#stream_readable_pipe_destination_options

или краткое объяснение: readable.pipe(writable) Функция pipe () читает данные из читаемого потока, когда они становятся доступными, и записывает их в целевой поток записи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...