一个关于Nodejs的fs模块读取文件的疑惑

一个关于Nodejs的fs模块读取文件的疑惑

目的:读取output.txt文件中第10-14字节并打印.

存在ouput.txt 文件内容为 ABCDEFGHIJKLMNOP

示例程序为:

var fs=require(‘fs’); fs.open(__dirname+’/a.txt’,‘r’,function(err,fd){ if(err){throw err;} var buffer=new Buffer(5); var readBytes=0;

(function readIt(){
    fs.read(fd,buffer,readBytes,buffer.length-readBytes,10+readBytes,function(err,bytesRead){
        if(err){throw err;}
        readBytes+=bytesRead; 
        if(readBytes===buffer.length){
            console.log(buffer);
        }else{
            readIt();
        }
    });
})();

});

上代码运行正确,但请教各位,代码中 readBytes+=bytesRead; 语句,以及下面的if循环到底起到了什么作用,是否可以给分析下,谢谢.


4 回复

这不是一次性读取文件内容的,每次readIt()只读取了指定范围的内容,readBytes+=bytesRead是累计计算读取的内容大小,if else是判断是否读取完了


当然可以。让我们来分析一下你提供的代码,并解释 readBytes += bytesRead;if (readBytes === buffer.length) 这两行代码的作用。

目标

读取 output.txt 文件中第10到14个字节,并打印出来。

示例代码

var fs = require('fs');

// 打开文件
fs.open(__dirname + '/output.txt', 'r', function(err, fd) {
    if (err) { throw err; }

    // 创建缓冲区,大小为5字节
    var buffer = new Uint8Array(5);
    var readBytes = 0;

    // 递归函数用于读取文件
    (function readIt() {
        // 从文件中读取数据到缓冲区
        fs.read(fd, buffer, readBytes, buffer.length - readBytes, 10 + readBytes, function(err, bytesRead) {
            if (err) { throw err; }

            // 更新已读字节数
            readBytes += bytesRead;

            // 如果已经读取了所有需要的数据,则打印结果
            if (readBytes === buffer.length) {
                console.log(buffer);
            } else {
                // 否则继续读取剩余的数据
                readIt();
            }
        });
    })();
});

代码解析

  1. 打开文件

    fs.open(__dirname + '/output.txt', 'r', function(err, fd) {
        if (err) { throw err; }
    

    使用 fs.open 打开文件,如果出错则抛出错误。

  2. 创建缓冲区

    var buffer = new Uint8Array(5);
    var readBytes = 0;
    

    创建一个5字节的缓冲区,并初始化已读字节数为0。

  3. 递归读取函数

    (function readIt() {
        fs.read(fd, buffer, readBytes, buffer.length - readBytes, 10 + readBytes, function(err, bytesRead) {
            if (err) { throw err; }
    
            readBytes += bytesRead;
            if (readBytes === buffer.length) {
                console.log(buffer);
            } else {
                readIt();
            }
        });
    })();
    
    • fs.read: 从文件描述符 fd 中读取数据到 buffer,从当前位置开始读取 buffer.length - readBytes 字节。
    • readBytes += bytesRead;: 更新已读字节数。
    • if (readBytes === buffer.length): 如果已经读取了5个字节(即缓冲区的长度),则打印缓冲区内容。
    • else { readIt(); }: 否则继续调用 readIt() 函数读取剩余的数据。

解释

  • readBytes += bytesRead; 更新当前已读字节数。
  • if (readBytes === buffer.length) 判断是否已经读取完缓冲区的所有字节。如果是,则打印缓冲区内容;否则,继续递归读取。

这样可以确保每次读取的数据都被正确累加到缓冲区中,并且当缓冲区被填满时打印结果。

在你的示例代码中,readBytes += bytesRead; 这一行的作用是追踪已经读取的字节数。而 if (readBytes === buffer.length) 这个条件判断则是用来检查是否已经读取了缓冲区中所有的字节。

具体来说,这段代码使用递归的方式去读取文件中的多个部分(每次读取5个字节),直到读取到目标位置(第10-14字节)。如果每次读取都恰好读满缓冲区的长度,则打印该缓冲区内容。

下面是简化后的代码,直接读取第10-14字节,并且打印出来:

const fs = require('fs');
const { createReadStream } = require('fs');

fs.open(__dirname + '/output.txt', 'r', (err, fd) => {
    if (err) throw err;

    const buffer = new Uint8Array(5); // 创建一个5字节大小的缓冲区

    fs.read(fd, buffer, 0, buffer.length, 9, (err, bytesRead) => { // 从第10个字节开始读取
        if (err) throw err;

        // 将Buffer转换为字符串并打印
        const result = buffer.slice(0, bytesRead).toString();
        console.log(result); // 输出结果应为 "KLMNO"
        
        fs.close(fd, () => {}); // 关闭文件描述符
    });
});

在这个简化的版本中,我们直接从第10个字节开始读取5个字节,并将其转换为字符串后打印。这样可以避免递归调用,使代码更简洁易懂。

回到顶部