【发布时间】:2019-03-09 08:51:53
【问题描述】:
我只是在学习 javascript,在学习一门新语言时我执行的一项常见任务是编写一个 hex-dump 程序。要求是 1. 读取命令行提供的文件,2. 能够读取大文件(一次读取缓冲区),3. 输出十六进制数字和可打印的 ascii 字符。
尽我所能,我无法让 fs.read(...) 函数实际执行。这是我开始使用的代码:
console.log(process.argv);
if (process.argv.length < 3) {
console.log("usage: node hd <filename>");
process.exit(1);
}
fs.open(process.argv[2], 'r', (err,fd) => {
if (err) {
console.log("Error: ", err);
process.exit(2);
} else {
fs.fstat(fd, (err,stats) => {
if (err) {
process.exit(4);
} else {
var size = stats.size;
console.log("size = " + size);
going = true;
var buffer = new Buffer(8192);
var offset = 0;
//while( going ){
while( going ){
console.log("Reading...");
fs.read(fd, buffer, 0, Math.min(size-offset, 8192), offset, (error_reading_file, bytesRead, buffer) => {
console.log("READ");
if (error_reading_file)
{
console.log(error_reading_file.message);
going = false;
}else{
offset += bytesRead;
for (a=0; a< bytesRead; a++) {
var z = buffer[a];
console.log(z);
}
if (offset >= size) {
going = false;
}
}
});
}
//}
fs.close(fd, (err) => {
if (err) {
console.log("Error closing file!");
process.exit(3);
}
});
}
});
}
});
如果我注释掉 while() 循环,read() 函数会执行,但当然只执行一次(适用于 8K 以下的文件)。现在,我只是没有看到像这样采用缓冲区和偏移量的 read() 函数的目的......有什么诀窍?
节点 v8.11.1,OSX 10.13.6
【问题讨论】:
-
为什么不调试你的程序看看发生了什么?
-
@JeroenHeier 刚试过,它只是跳过 fs.read() 函数和循环。
-
好吧,
fs.read()是异步的,因此它在while()循环中不会按照您希望的方式工作。我建议您使用该流中的fs.createReadStream()和data事件。然后,数据将在一系列事件中提供给您。而且,要在 node.js 中做任何有用的事情,您确实需要了解异步 I/O 的概念以及如何使用它进行编程。 -
@jfriend00 谢谢,这很有帮助。我将为 createReadSteam() 方法重构...但我仍然很好奇 fs.read() 方法有什么价值?
-
你明白
fs.read()是非阻塞的吗?你调用它,它开始一个读取操作,它立即返回并且你的while()循环继续执行调用一大堆更多的fs.read()操作。事实上,while循环会一直持续下去,因为它永远不会停止,所以它永远不会让事件循环有机会处理您的任何fs.read()完成事件。正如我上面所说,您不能将非阻塞操作放在while循环中,并且像阻塞一样进行编程。
标签: javascript node.js file while-loop binary