Ошибка: невозможно создать строку длиной более 0x3fffffe7 символов при использовании createReadStream

Я разбираю очень большие файлы CSV (~37 ГБ). Я используюfs.createReadStreamи csv-парсер. Я разбиваю их на 5000 строк, а затем вставляю их в mongo db. Однако эта ошибка возникает, даже если часть mongo закомментирована.

Вот функция для анализа файла:

function parseCsv(fileName: string, db: Db): Promise<any[]> {
    let parsedData: any[] = [];
    let counter = 0;
    return new Promise((resolve, reject) => {
        const stream = fs.createReadStream(fileName)
            .pipe(csvParser())
            .on('data', async (row) => {
                const data = parseData(row);
                parsedData.push(data);

                if (parsedData.length > 5000) {
                    stream.pause();
                    // insert to mongo
                    counter++;
                    console.log('counter - ', counter, parsedData[0].personfirstname, parsedData[23].personfirstname);
                    parsedData = [];

                    // try {
                    //  await db.collection('people').insertMany(parsedData, { ordered: false });
                    //  parsedData = [];
                    // }
                    // catch (e) {
                    //  console.log('error happened', e, parsedData.length);
                    //  process.exit();
                    // }

                    stream.resume();
                }
            })
            .on('error', (error) => {
                console.error('There was an error reading the csv file', error);
            })
            .on('end', () => {
                console.log('CSV file successfully processed');
                resolve()
            });
    });
}

А вот и функция для анализа данных. Это как-то беспорядочно со всеми значениями в одной ячейке, разделенными трубами, поэтому я просто разделил их:

function parseData(data: any) {
    let values = '';
    for (var key in data) {
        if (data.hasOwnProperty(key)) {
            values += data[key];
        }
    }
    const splitValues = values.split('|');
    let parsedData: any = {};

    // Remove deep reference
    parsedData = JSON.parse(JSON.stringify(template));
    let keyCounter = 0;
    for (let key in parsedData) {
        if (parsedData.hasOwnProperty(key)) {
            try {
                parsedData[key] = splitValues[keyCounter].trim();
            }
            catch (e) {
                console.log('error probably trimming', key, splitValues[keyCounter], splitValues, data);
                throw '';
            }
            keyCounter++;
        }
    }

    const now = new Date();
    parsedData.createdAt = now;
    parsedData.updatedAt = now;
    return parsedData;
}

Он отлично разбирается (до ~2 миллионов строк), а затем зависает. Наконец, оставив его висеть всю ночь, я проверил утром и увидел следующую ошибку:

buffer.js:580
      if (encoding === 'utf-8') return buf.utf8Slice(start, end);
                                           ^

Error: Cannot create a string longer than 0x3fffffe7 characters
    at stringSlice (buffer.js:580:44)
    at Buffer.toString (buffer.js:643:10)
    at CsvParser.parseValue (C:\js_scripts\csv-worker\node_modules\csv-parser\index.js:175:19)
    at CsvParser.parseCell (C:\js_scripts\csv-worker\node_modules\csv-parser\index.js:86:17)
    at CsvParser.parseLine (C:\js_scripts\csv-worker\node_modules\csv-parser\index.js:142:24)
    at CsvParser._flush (C:\js_scripts\csv-worker\node_modules\csv-parser\index.js:196:10)
    at CsvParser.prefinish (_stream_transform.js:140:10)
    at CsvParser.emit (events.js:200:13)
    at prefinish (_stream_writable.js:633:14)
    at finishMaybe (_stream_writable.js:641:5) {
  code: 'ERR_STRING_TOO_LONG'
}

Не должен createReadStreamубедиться, что этого не произойдет? В каждой строке 415 столбцов. Возможно ли, что одна строка слишком велика? Он всегда останавливается в одном и том же месте, так что это кажется вероятным. Поскольку файлы такие большие, у меня нет возможности их открыть. Если да, то как я могу это обнаружить и просто пропустить эту строку или обработать по-другому?

0 ответов

Другие вопросы по тегам