node.js 读取文件问题

标签 node.js

下面的一段代码创建了一个文本文件,然后读取它,覆盖它,然后再次读取它。除了创建文件外,这三个 I/O 操作都是使用 Node.js async readFile 和 writeFile 执行的。

我不明白为什么第一次读取返回无错误无数据。这段代码的输出是:

  • 开始...
  • 完成。
  • 首先读取返回的 EMPTY 数据!
  • 写完OK
  • 第二次读取返回数据:更新文本

即使操作以任意顺序发生(由于它们的异步性质),我也不希望得到一个“空数据”对象。

为什么我在读取文件时得到一个空数据(并且没有错误)有什么想法吗?

我可以做些什么来确保读取文件内容吗?

var fs = require('fs');
var fileName = __dirname + '/test.txt';

// Create the test file (this is sync on purpose)
fs.writeFileSync(fileName, 'initial test text', 'utf8');


console.log("Starting...");

// Read async
fs.readFile(fileName, 'utf8', function(err, data) {
    var msg = "";
    if(err)
        console.log("first read returned error: ", err);
    else {
        if (data === null) 
            console.log("first read returned NULL data!");
        else if (data === "") 
            console.log("first read returned EMPTY data!");
        else
            console.log("first read returned data: ", data);
    }
});


// Write async
fs.writeFile(fileName, 'updated text', 'utf8', function(err) {
    var msg = "";
    if(err)
        console.log("write finished with error: ", err);
    else
        console.log("write finished OK");
});


// Read async
fs.readFile(fileName, 'utf8', function(err, data) {
    var msg = "";
    if(err)
        console.log("second read returned error: ", err);
    else
        if (data === null) 
            console.log("second read returned NULL data!");
        else if (data === "") 
            console.log("second read returned EMPTY data!");
        else
            console.log("second read returned data: ", data);
});


console.log("Done.");

最佳答案

您的代码要求竞争条件。您的第一次同步写入可能是在写入文件,但随后您的第一次读取、第二次写入和第二次读取被同时放入事件循环。

这里可能发生了什么?第一次读取从文件系统获得读取权限,第二次写入从文件系统获得写入权限并立即将文件清零以备将来更新,然后第一次读取读取现在为空的文件。然后第二次写入开始写入数据,第二次读取直到完成才获得读取权限。

如果你想避免这种情况,你需要使用流程:

fs.writeFileSync(filename, 'initial', 'utf8');
fs.readFile(filename, 'utf8', function(err, data) {
    console.log(data);
    fs.writeFile(filename, 'text', 'utf8', function(err) {
        fs.readFile(filename, 'utf8', function(err, data) {
            console.log(data);
        });
    });
});

如果那个“金字塔”侮辱了你的编程敏感性(为什么不呢?)使用 async libraryseries 函数:

fs.writeFileSync(filename, 'initial', 'utf8');
async.series([
    function(callback) {
        fs.readFile(filename, 'utf8', callback);
    },
    function(callback) {
        fs.writeFile(filename, 'text', 'utf8', callback);
    },
    function(callback) {
        fs.readFile(filename, 'utf8', callback);
    }
], function(err, results) {
    if(err) console.log(err);
    console.log(results); // Should be: ['initial', null, 'text']
});

编辑:对于不熟悉 async 库和现代 Javascript 功能的人来说更紧凑,但也更“神奇”:

fs.writeFileSync(filename, 'initial', 'utf8');
async.series([
    fs.readFile.bind(this, filename, 'utf8'),
    fs.writeFile.bind(this, filename, 'text', 'utf8'),
    fs.readFile.bind(this, filename, 'utf8'),
], function(err, results) {
    if(err) console.log(err);
    console.log(results); // Should be: ['initial', null, 'text']
});

EDIT2:无需查看 bind 的定义即可为我进行编辑。第一个参数需要是 this 对象(或者任何你想用作 this 的对象)。

关于node.js 读取文件问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10368806/

相关文章:

java - 如何从我的 EC2/Node.js 应用程序在另一个 AWS EC2 中运行 java jar 文件?

node.js - 有没有办法在 REST API 中访问 express 的应用程序?

node.js - 将 CompoundJs 与 Passport 结合使用

node.js - 如何桥接字节数组和音频流?

javascript - 在本地运行 Node 与在 Web 服务器上安装 Node 有何不同?

node.js - 如何仅为后端安装 meteor ?

node.js - Azure无法加载共享库-使用nodejs

node.js - Casper --proxy 不起作用

mongodb - Mongoose + Everyauth 奇怪的行为

node.js - 我可以在 ES6 中使用服务器端 Node js 并且仍然不使用 bable