javascript - Grabbing a random line from file - Stack Overflow

I have no idea on how to do this. Where should I start? I have googled this and not one result came up

I have no idea on how to do this. Where should I start? I have googled this and not one result came up on how to pull a random line from a text file.

The only thing I have found is , however it doesn't work. How can I read a random line from a text file?

I have no idea on how to do this. Where should I start? I have googled this and not one result came up on how to pull a random line from a text file.

The only thing I have found is https://github.com/chrisinajar/node-rand-line, however it doesn't work. How can I read a random line from a text file?

Share Improve this question asked Nov 15, 2012 at 5:33 mikemike 1711 gold badge1 silver badge3 bronze badges 2
  • 1 How big is this file? One easy method is to read the whole file, and pick a random line. However, this takes at least as much memory as the file. – Brad Commented Nov 15, 2012 at 5:37
  • 2MB? just read it into the memory – Dmitry Commented Nov 15, 2012 at 7:04
Add a comment  | 

5 Answers 5

Reset to default 13

You would probably want to look at the node.js standard library function for reading files, fs.readFile, and end up with something along the lines of:

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);
 })
}

If reading the whole thing and splitting isn't an option, then maybe have a look at this stack overflow for ideas.

I had the same kind of need to pick a random line from a file of more than 100 Mo.
So I wanted to avoid storing all the file content in memory.
I ended up iterating over all the lines twice: first to get the lines count, then to get target line content.
Here is what the code looks like:

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++;
        });
    });
}

I don't have Node handy to test code, so I can't give you exact code, but I would do something like this:

  1. Get the file size in bytes, pick a random byte offset
  2. Open the file as a stream
  3. Use this snippet to emit lines (or readline, but last I used it had a nasty bug where it essentially didn't work)
  4. Keep track of your position in the file as you read. As you pass your chosen offset, select that line and return it.

Note that this isn't entirely random. Longer lines will be weighted more heavily, but it is the only way to do it without reading the whole file to get a count of lines.

This method allows you to get a "random" line without keeping the whole file in memory.

I did it like this

const path = require('path')
const fs = require('fs/promises')

const FILE_NAME = path.resolve(__dirname, '../bigfile.txt')
const DELIMITER = '\n'

const READ_BUFFER_SIZE = 1000 // Must be greater than the record size

/*
 * Reading a random line from a very large (does not fit in RAM) file
 *
 * Note that you will never get the first or last line in the file,
 * but who cares when the file contains millions of lines.
 */
async function main() {
    const stats = await fs.stat(FILE_NAME)
    const handle = await fs.open(FILE_NAME, 'r')

    for (;;) {
        const randomPos = Math.floor(Math.random() * stats.size)

        const buffer = Buffer.alloc(READ_BUFFER_SIZE)
        await handle.read(buffer, 0, READ_BUFFER_SIZE, randomPos)

        const xs = buffer.toString().split(DELIMITER)
        if (xs[2] !== undefined) {
            console.log('Random line:', xs[1])
        }
    }
}
main().catch(console.log)

I can give you a suggestion as I don't have any demo code

  1. Read the file line by line using buffered reader
  2. Store every line in a String array
  3. Create a method int returnRandom(arraySize)
  4. Pass the array size in to the function
  5. Calculate a random number between 0 to arraySize
  6. Return the random number
  7. Print the given index from your string array

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1738178085a4029287.html

相关推荐

  • javascript - Grabbing a random line from file - Stack Overflow

    I have no idea on how to do this. Where should I start? I have googled this and not one result came up

    1天前
    20

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信