如何将异步输出重定向到文件?
How do I redirect asynchronous output to a file?
我有一个 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
,但是处理这个问题的正确方法是什么?
问题是
- 您正在打开文件进行阅读,
- 然后打开文件进行写入(清空),
- 然后从一个空文件中读取。
- 什么都不改变
- 什么都不写
我认为你想要的是:
- 开放阅读
- 读取和缓冲
- 变换
- 打开写入
- 写
有几种方法可以做到这一点:
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) 使用"streams"
这真是最好的办法。特别是如果你想学习 Node.js
据我所知,学习流的最好方法是从 NodeSchool:http://nodeschool.io/#workshoppers 试试 stream-adventure
。
到最后,您将拥有这些类型的问题。
祝你好运!
问题实际上不在 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
)。
我有一个 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
,但是处理这个问题的正确方法是什么?
问题是
- 您正在打开文件进行阅读,
- 然后打开文件进行写入(清空),
- 然后从一个空文件中读取。
- 什么都不改变
- 什么都不写
我认为你想要的是:
- 开放阅读
- 读取和缓冲
- 变换
- 打开写入
- 写
有几种方法可以做到这一点:
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) 使用"streams"
这真是最好的办法。特别是如果你想学习 Node.js
据我所知,学习流的最好方法是从 NodeSchool:http://nodeschool.io/#workshoppers 试试 stream-adventure
。
到最后,您将拥有这些类型的问题。
祝你好运!
问题实际上不在 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
)。