从文本文件中读取第一行而不将整个文本文件加载到内存中

Posted

技术标签:

【中文标题】从文本文件中读取第一行而不将整个文本文件加载到内存中【英文标题】:Reading first lines from textfile without loading whole textfile into memory 【发布时间】:2020-06-13 14:05:24 【问题描述】:

我有大量的小文本文件,其中前 4 行或更少的行包含元数据;下面是一个例子

Lorem Ipsum

标签1 标签2 标签3

文字

4204

‎‎‎‎‎‎

Lorem ipsum dolor sit amet,consectetur adipiscing elit,sed do eiusmod tempor incididunt ut labore et dolore magna aliqua。 Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat。 Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur。 Exceptioneur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum。

Lo​​rem Ipsum;将是标题 标签 1、标签 2 和标签 3;将是一个标签数组 文本;将是类型 4204;将是 ID。 Lo​​rem ipsum [...];将是实际内容

我需要加载元数据而不加载实际内容。我在 node.js 工作。我做了以下代码:

function readMeta (path, callback) 
    const meta = ;
    const lineReader = require("readline").createInterface(input: require("fs").createReadStream(path));

    let lineCount = 0;
    let interpretedMeta;

    lineReader.on("line", line => 

        interpretedMeta = interpretMeta(line, lineCount) 

        switch (lineCount) 
            case 0:
                meta.name = interpretedMeta;
                break;
            case 1:
                meta.tags = interpretedMeta.split(" ");
                break;
            case 2:
                meta.type = interpretedMeta;
                break;
            case 3:
                meta.id = interpretedMeta;
        

        ++lineCount;


        if (/^\s*$/.test(line)) 
            lineReader.close();
        
    );
    lineReader.on("close", () => 
    callback(meta);
    process.exit(0);
    );

其中interpretMeta() 是一个根据行号格式化给定字符串的函数。稍后我会将它整合到 readMeta() 中,因为它有些多余。

问题

此代码适用于一个文件,但如果它在短时间内运行多次,则会出现错误。它到达第二行,但每次函数运行时都会重新开始。

我不是 100% 确定为什么会发生这种情况,但我假设像 lineReader.on() 的回调不会复制从 readMeta 获得的变量。我不知道如何调试或解决。

修复

我没有任何使用异步函数的经验,所以如果我使用了错误的术语,我深表歉意:我相信解决我的问题的一种方法,我会很乐意使用,是读取下一行的同步 readline() 函数在一条溪流中。我不知道该怎么做,所以我的问题是我该怎么做:

A:修复代码

B: 做一个同步的‘readline’函数

谢谢

【问题讨论】:

这能回答你的问题吗? Read a file one line at a time in node.js? 我发现了一些我认为可以在较低答案之一中使用的东西,将尝试并在之后更新,谢谢。 【参考方案1】:

User O. Jones 评论了原帖,询问this answer 是否会回答我的问题。经过验证的答案没有,但User Lead Developer 的answer below 让我走上了正轨:

2019 年更新

Nodejs 官方文档中已经发布了一个很棒的示例。 here

这需要在您的机器上安装最新的 Nodejs。 >11.4

const fs = require('fs');
const readline = require('readline');

async function processLineByLine() 
const fileStream = fs.createReadStream('input.txt');

const rl = readline.createInterface(
   input: fileStream,
   crlfDelay: Infinity
);
// Note: we use the crlfDelay option to recognize all instances of CR LF
// ('\r\n') in input.txt as a single line break.

for await (const line of rl) 
   // Each line in input.txt will be successively available here as `line`.
   console.log(`Line from file: $line`);



processLineByLine();

page he links to 包含我最终遵循的另一个示例,以下是我的最终代码:

async function readMeta (path) 
    const meta = ;
    const lineReader = require("readline").createInterface(input: fs.createReadStream(path));

    let currentLine = 0;

    lineReader.on("line", line => 


        switch (currentLine) 
            case 0:
                meta.name = line;
                break;
            case 1:
                meta.tags = line.split(" ");
                break;
            case 2:
                meta.type = line;
                break;
            case 3:
                meta.id = +line;
        

        ++currentLine;


        if (/^\s*$/.test(line)) 
            lineReader.close();
        
    );
    await once(lineReader, "close");

    return meta;

感谢您的帮助。

【讨论】:

以上是关于从文本文件中读取第一行而不将整个文本文件加载到内存中的主要内容,如果未能解决你的问题,请参考以下文章

Gensim 构建字典而不将所有文本加载到内存中

Actionscript 3,只能读取文件的一部分而不将整个文件加载到内存中

python 以块的形式读取文件而不将整个文件加载到内存中。

从 Dask 数据帧中获取一行而不将整个数据帧加载到内存中

合并大文件而不将整个文件加载到内存中?

如何使用 Java 裁剪图像而不将其加载到内存中