如何将异步输出重定向到文件?

时间:2015-05-06 01:58:51

标签: javascript node.js asynchronous console.log

我有一个Node.js脚本,它读取文件的内容,对其内容进行一些转换,并记录输出:

var transformer = require('./transformer'),
    fs = require('fs'),
    file = process.argv[2];

if (!file) {
    throw 'no file specified\n';
}

fs.readFile(file, 'utf-8', function (err, data) {
    if (err) {
        throw err;
    }

    transformer.transform(data, function (text) {
        console.log(text);
    });
});

这很好用:

$ node transform.js myfile.txt

这有效:

$ node transform.js myfile.txt > anotherfile.txt

但是,当我尝试将输出重定向到我正在阅读的同一个文件时,该文件变为空白:

$ node transform.js myfile.txt > myfile.txt

使用tee同样的事情:

$ node transform.js myfile.txt | tee myfile.txt

奇怪的是,这有效:

$ node transform.js myfile.txt >> myfile.txt

但我不想附加到该文件 - 我想覆盖其内容。

我认为问题是,因为fs.readFile是异步的,所以console.log也是异步调用的 - 也就是说,它获取数据块而不是一次性所有数据。我想我可以使用fs.readFileSync代替,但是正确的方法是什么?

2 个答案:

答案 0 :(得分:1)

问题是

  • 您正在打开要阅读的文件
  • 然后打开文件进行写入(清空),
  • 然后从空文件中读取。
  • 不做任何改变
  • 什么都不写

我认为你想要的是:

  • 开放供阅读
  • 读取和缓冲
  • 变换
  • 开放写作

有几种方法可以做到这一点:

1)同步读取文件。 Node.js 0.12 supports this

var transformer = require('./transformer'),
    fs = require('fs'),
    file = process.argv[2];

if (!file) {
    throw 'no file specified\n';
}

fs.readFileSync(file, 'utf-8', function (err, data) {
    if (err) {
        throw err;
    }

    transformer.transform(data, function (text) {
        console.log(text);
    });
});

2)使用“溪流”

这是最好的方法。特别是如果你想学习Node.js

我了解流知识的最佳方式来自NodeSchool:http://nodeschool.io/#workshoppers尝试stream-adventure

最后,你拥有这类问题。

祝你好运!

答案 1 :(得分:1)

问题实际上不在Node内,而是在shell中。使用>重定向时,shell执行的第一件事是打开文件进行写入,清空文件。你的程序从那个空文件中读取,在你的情况下,空输入意味着空输出。

无论myfile.txt的初始内容是什么,这都会导致文件为空:

$ cat myfile.txt > myfile.txt 

一种解决方案是在Node脚本中编写文件而不是使用重定向。您已经在那里指定和读取文件,那么为什么不在argv中指定输出文件并写入它而不是使用shell重定向?只需要注意构建代码,以便读取和写入同一个文件。

正如@slebetman在评论中指出的那样,另一种解决方案是cat myfile.txt > tmp; mv tmp myfile.txt(或我的首选:cat myfile.txt > tmp && mv tmp myfile.txt)。