13

我不知道该怎么做。我应该从哪里开始?我已经用谷歌搜索了这个,但没有一个关于如何从文本文件中提取随机行的结果。

我唯一找到的是https://github.com/chrisinajar/node-rand-line,但是它不起作用。如何从文本文件中读取随机行?

4

4 回答 4

12

您可能希望查看用于读取文件的 node.js 标准库函数fs.readFile,并最终得到以下内容:

const fs = require("fs");
// note this will be async
function getRandomLine(filename, callback){
  fs.readFile(filename, "utf-8", function(err, data){
    if(err) {
        throw err;
    }

    // note: this assumes `data` is a string - you may need
    //       to coerce it - see the comments for an approach
    var lines = data.split('\n');
    
    // choose one of the lines...
    var line = lines[Math.floor(Math.random()*lines.length)]

    // invoke the callback with our line
    callback(line);
 })
}

如果阅读整个内容并拆分不是一种选择,那么也许可以看看这个堆栈溢出的想法。

于 2012-11-15T05:40:57.443 回答
3

我没有方便的 No​​de 来测试代码,所以我不能给你确切的代码,但我会做这样的事情:

  1. 以字节为单位获取文件大小,选择一个随机字节偏移量
  2. 将文件作为流打开
  3. 使用此代码段发出行(或readline,但最后我使用它有一个讨厌的错误,它基本上不起作用)
  4. 在阅读时跟踪您在文件中的位置。当您通过您选择的偏移量时,选择该行并返回它。

请注意,这并非完全随机。较长的行将被赋予更大的权重,但这是唯一无需读取整个文件来获取行数的方法。

此方法允许您获得“随机”行,而无需将整个文件保存在内存中。

于 2012-11-15T05:44:01.273 回答
2

我有同样的需要从超过 100 Mo 的文件中随机选择一行。
所以我想避免将所有文件内容存储在内存中。
我最终对所有行进行了两次迭代:首先获取行数,然后获取目标行内容。
代码如下所示:

const readline = require('readline');
const fs = require('fs');
const FILE_PATH = 'data.ndjson';

module.exports = async () =>
{
    const linesCount = await getLinesCount();
    const randomLineIndex = Math.floor(Math.random() * linesCount);
    const content = await getLineContent(randomLineIndex);
    return content;
};

//
// HELPERS
//

function getLineReader()
{
    return readline.createInterface({
        input: fs.createReadStream(FILE_PATH)
    });
}

async function getLinesCount()
{
    return new Promise(resolve =>
    {
        let counter = 0;
        getLineReader()
        .on('line', function (line)
        {
            counter++;
        })
        .on('close', () =>
        {
            resolve(counter);
        });
    });
}

async function getLineContent(index)
{
    return new Promise(resolve =>
    {
        let counter = 0;
        getLineReader().on('line', function (line)
        {
            if (counter === index)
            {
                resolve(line);
            }
            counter++;
        });
    });
}
于 2019-07-01T17:31:58.477 回答
0

我可以给你一个建议,因为我没有任何演示代码

  1. 使用逐行读取文件buffered reader
  2. 将每一行存储在一个字符串数组中
  3. 创建一个方法int returnRandom(arraySize)
  4. 将数组大小传递给函数
  5. 计算之间的随机0arraySize
  6. 返回随机数
  7. 从字符串数组中打印给定的索引
于 2012-11-15T06:03:56.393 回答