Node.js readline + fs. createReadStream : укажите номер начальной и конечной строки

https://nodejs.org/api/readline.html

предоставляет это решение для чтения больших файлов, таких как CSV, построчно:

const { createReadStream } = require('fs');
const { createInterface } = require('readline');

(async function processLineByLine() {
  try {
    const rl = createInterface({
      input: createReadStream('big-file.txt'),
      crlfDelay: Infinity
    });

    rl.on('line', (line) => {
      // Process the line.
    });

    await once(rl, 'close');

    console.log('File processed.');
  } catch (err) {
    console.error(err);
  }
})();

Но я не хочу читать весь файл от начала до конца, но его части говорят от строки с номером 1 до 10000, от 20000 до 30000 и т. д.

В основном я хочу иметь возможность установить строку «начало» и «конец» для данного запуска моей функции.

Это выполнимо с readline и fs.createReadStream? Если нет, предложите альтернативный подход.

PS: это большой файл (около 1 ГБ), и его загрузка в память вызывает проблемы с памятью.


person jackOfAll    schedule 30.06.2021    source источник
comment
Все ли линии одинакового размера?   -  person leitning    schedule 30.06.2021
comment
вы видели stackoverflow .com/questions/45556535/   -  person Lawrence Cherone    schedule 01.07.2021
comment
Если ваши строки не имеют фиксированной одинаковой длины, НЕТ способа узнать, где начинается строка 10 000, без чтения с начала файла и подсчета строк, пока вы не дойдете до строки 10 000. Вот как работают текстовые файлы со строками переменной длины. Нет никакого способа обойти это, если вы предварительно не обработаете файл в более эффективный формат (например, базу данных) или не создадите индекс позиций строк.   -  person jfriend00    schedule 01.07.2021
comment
Э-э, проблемы с памятью для больших файлов можно решить с помощью потоков, когда у вас в любой момент времени в памяти находится только небольшая часть файла, независимо от того, насколько велик общий файл.   -  person jfriend00    schedule 01.07.2021
comment
@lawrence, я хотел пропустить повторение.   -  person jackOfAll    schedule 01.07.2021


Ответы (2)


Но я не хочу читать весь файл от начала до конца, но его части говорят от строки с номером 1 до 10000, от 20000 до 30000 и т. д.

Если ваши строки не имеют фиксированной одинаковой длины, НЕТ способа узнать, где начинается строка 10 000, без чтения с начала файла и подсчета строк, пока вы не дойдете до строки 10 000. Вот как работают текстовые файлы со строками переменной длины. Строки в файле не являются физическими структурами, о которых файловая система ничего не знает. Для файловой системы файл — это просто гигантский блок данных. Концепция строк — это то, что мы изобретаем на более высоком уровне, и поэтому файловая система или ОС ничего не знают о строках. Единственный способ узнать, где находятся строки, — прочитать данные и разбить их на строки, выполнив поиск разделителей строк. Таким образом, строка 10 000 находится только путем поиска разделителя 10 000-й строки, начиная с начала файла и считая.

Нет никакого способа обойти это, если вы предварительно не обработаете файл в более эффективный формат (например, базу данных) или не создадите индекс позиций строк.

В основном я хочу иметь возможность установить строку «начало» и «конец» для данного запуска моей функции.

Единственный способ сделать это — заранее проиндексировать данные, чтобы вы уже знали, где начинается/заканчивается каждая строка. Некоторые текстовые редакторы, предназначенные для работы с очень большими файлами, делают это. Они читают файл (возможно, лениво), считывая каждую строку, и строят в памяти индекс того, с какого смещения файла начинается каждая строка. Затем они могут получить определенные блоки строк, обратившись к индексу и прочитав этот набор данных из файла.

Это выполнимо с помощью readline и fs.createReadStream?

Без строк фиксированной длины невозможно узнать, где в файле начинается строка 10 000, не считая с самого начала.

Это большой файл (около 1 ГБ), и его загрузка в память вызывает ПРОБЛЕМЫ ПАМЯТИ.

Потоковая передача файла построчно с помощью модуля чтения строк или других, которые делают что-то подобное, прекрасно справятся с проблемой памяти, так что в любой момент времени в памяти находится только блок данных из файла. Таким образом вы можете обрабатывать произвольно большие файлы даже в системе с небольшой памятью.

person jfriend00    schedule 01.07.2021
comment
Спасибо, что так быстро и подробно ответили. - person jackOfAll; 01.07.2021

Новая строка - это просто символ (или два символа, если вы работаете в Windows), у вас нет возможности узнать, где находятся эти символы, без обработки файла.

Однако вы можете прочитать только определенный диапазон байтов в файле. Если вы точно знаете, что каждая строка содержит 64 байта, вы можете пропустить первые 100 строк, начав чтение с байта 6400, и вы сможете прочитать только 100 строк, остановив чтение на 12800 байте.

Подробная информация о том, как указать начальную и конечную точки, доступна в документах createReadStream.

person leitning    schedule 30.06.2021