node.js 读取文件问题 [英] node.js readfile woes

查看:64
本文介绍了node.js 读取文件问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码创建了一个文本文件,然后读取、覆盖并再次读取.除了创建文件之外,三个 I/O 操作都是使用 Node.js 异步 readFile 和 writeFile 执行的.

The following piece of code creates a text file and then reads it, overwrites it, and reads it again. Except the creation of the file the three I/O operations are performed using Node.js async readFile and writeFile.

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

I don't understand why the first read is returning no error but no data either. The output of this code is:

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

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

Even if the operations were to happen in an arbitrary order (due to their async nature) I would have NOT expected to get an "empty data" object.

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

Any ideas why I am getting an empty data when reading the file (and no error) ?

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

Is there anything that I can do to make sure the file content is read?

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.");

推荐答案

您的代码正在询问竞争条件.您的第一次同步写入可能正在写入文件,但随后您的第一次读取、第二次写入和第二次读取被同时放入事件循环中.

Your code is asking for race conditions. Your first sync write is probably writing the file, but then your first read, second write, and second read are put onto the event loop simultaneously.

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

What could have happened here? First read gets read permission from the filesystem, second write gets write permission from the filesystem and immediately zeroes the file for future updating, then the first read reads the now empty file. Then the second write starts writing data and the second read doesn't get read permission until it's done.

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

If you want to avoid this, you need to use the flow:

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

如果那个金字塔"侮辱了你的编程敏感性(为什么不呢?)使用 异步库series函数:

If that "pyramid" insults your programming sensibilities (why wouldn't it?) use the async library's series function:

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 功能的人来说,更紧凑,但也更神奇":

More compact, but also more "magical" to people not familiar with the async library and modern Javascript features:

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

让我在不查找 bind 定义的情况下进行编辑是正确的.第一个参数需要是 this 对象(或者任何你想用作 this 的对象).

Serves me right for making that edit without looking up the definition of bind. The first parameter needs to be the this object (or whatever you want to use as this).

这篇关于node.js 读取文件问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆