在node.js中一次读取一个字符的文件?

Posted

技术标签:

【中文标题】在node.js中一次读取一个字符的文件?【英文标题】:Read a file one character at a time in node.js? 【发布时间】:2015-07-17 18:25:32 【问题描述】:

有没有办法在 nodejs 中一次从文件中读取一个符号而不将整个文件存储在内存中? 我找到了lines的答案

我尝试了类似的方法,但没有帮助:

const stream = fs.createReadStream("walmart.dump", 
    encoding: 'utf8',
    fd: null,
    bufferSize: 1,
);
stream.on('data', function(sym)
    console.log(sym);
);

【问题讨论】:

【参考方案1】:

可读流有一个read() 方法,您可以在其中传递要读取的每个块的长度(以字节为单位)。例如:

var readable = fs.createReadStream("walmart.dump", 
    encoding: 'utf8',
    fd: null,
);
readable.on('readable', function() 
  var chunk;
  while (null !== (chunk = readable.read(1) /* here */)) 
    console.log(chunk); // chunk is one byte
  
);

【讨论】:

【参考方案2】:

这是一种较低级别的方法:fs.read(fd, buffer, offset, length, position, callback)

使用:

const fs = require('fs');

// open file for reading, returns file descriptor
const fd = fs.openSync('your-file.txt','r');

function readOneCharFromFile(position, cb)

        // only need to store one byte (one character)
        const b = new Buffer(1);

        fs.read(fd, b, 0, 1, position, function(err,bytesRead, buffer)
            console.log('data => ', String(buffer));
            cb(err,buffer);
        );


您必须在读取文件时增加位置,但它会起作用。

这是一个如何逐个字符读取整个文件的快速示例

只是为了好玩,我编写了这个完整的脚本来完成它,只需传入不同的文件路径,它应该可以工作

const async = require('async');
const fs = require('fs');
const path = require('path');


function read(fd, position, cb) 

    let isByteRead = null;
    let ret = new Buffer(0);

    async.whilst(
        function () 
            return isByteRead !== false;
        ,
        function (cb) 
            readOneCharFromFile(fd, position++, function (err, bytesRead, buffer) 

                if(err)
                    return cb(err);
                

                isByteRead = !!bytesRead;
                if(isByteRead)
                    ret = Buffer.concat([ret,buffer]);
                

                cb(null);
            );
        ,
        function (err) 
            cb(err, ret);
        
    );




function readOneCharFromFile(fd, position, cb) 

    // only need to store one byte (one character)
    const b = new Buffer(1);
    fs.read(fd, b, 0, 1, position, cb);




 /// use your own file here
const file = path.resolve(__dirname + '/fixtures/abc.txt');
const fd = fs.openSync(file, 'r');

// start reading at position 0, position will be incremented
read(fd, 0, function (err, data) 
    if (err) 
        console.error(err.stack || err);
    
    else 
        console.log('data => ', String(data));
    
    fs.closeSync(fd);
);

如您所见,每次读取文件时我们都会增加位置整数。希望操作系统在我们进行时将文件保存在内存中。使用 async.whilst() 是可以的,但我认为对于更实用的样式,最好不要将状态保持在函数的顶部(ret 和 isByteRead)。我将把它作为练习留给读者来实现,而不使用那些有状态的变量。

【讨论】:

fs.openSync 将立即读取整个文件...这与 OP 想要的相反。

以上是关于在node.js中一次读取一个字符的文件?的主要内容,如果未能解决你的问题,请参考以下文章

保持生成过程中的 Node.js 结果有序

在 node.js 中一次遍历一个包含 50 个项目的数组

Node.js的Buffer写入

如何在 Node.js 中读取文件?

Node.js - 如何将流转换为字符串

无法在 ejs 文件 (node.js) 中读取 null 的属性“名称”