node.js:从标准输入读取同步?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3430939/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
node.js: readSync from stdin?
提问by panzi
Is it possible to synchronously read from stdin in node.js? Because I'm writing a brainfwor to JavaScript compiler in JavaScript (just for fun). Brainfwor supports a read operation which needs to be implemented synchronously.
是否可以从 node.js 中的 stdin 同步读取?因为我正在用 JavaScript 编写 JavaScript 编译器的脑残粉(只是为了好玩)。Brainfwor 支持需要同步实现的读操作。
I tried this:
我试过这个:
const fs = require('fs');
var c = fs.readSync(0,1,null,'utf-8');
console.log('character: '+c+' ('+c.charCodeAt(0)+')');
But this only produces this output:
但这只会产生以下输出:
fs:189
var r = binding.read(fd, buffer, offset, length, position);
^
Error: EAGAIN, Resource temporarily unavailable
at Object.readSync (fs:189:19)
at Object.<anonymous> (/home/.../stdin.js:3:12)
at Module._compile (module:426:23)
at Module._loadScriptSync (module:436:8)
at Module.loadSync (module:306:10)
at Object.runMain (module:490:22)
at node.js:254:10
采纳答案by rjp
I've no idea when this showed up but this is a helpful step forward: http://nodejs.org/api/readline.html
我不知道这什么时候出现,但这是向前迈出的有用的一步:http: //nodejs.org/api/readline.html
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
});
rl.on('line', function (cmd) {
console.log('You just typed: '+cmd);
});
Now I can read line-at-a-time from stdin. Happy days.
现在我可以从标准输入中一次读取一行。快乐的时光。
回答by dhruvbird
Have you tried:
你有没有尝试过:
fs=require('fs');
console.log(fs.readFileSync('/dev/stdin').toString());
However, it will wait for the ENTIRE file to be read in, and won't return on \n like scanf or cin.
但是,它将等待整个文件被读入,并且不会像 scanf 或 cin 那样在 \n 上返回。
回答by Marcus Pope
After fiddling with this for a bit, I found the answer:
在摆弄了一会儿之后,我找到了答案:
process.stdin.resume();
var fs = require('fs');
var response = fs.readSync(process.stdin.fd, 100, 0, "utf8");
process.stdin.pause();
response will be an array with two indexes, the first being the data typed into the console and the second will be the length of the data including the newline character.
response 将是一个有两个索引的数组,第一个是输入到控制台的数据,第二个是包括换行符在内的数据长度。
It was pretty easy to determine when you console.log(process.stdin)which enumerates all of the properties including one labeled fdwhich is of course the name of the first parameter for fs.readSync()
很容易确定何时console.log(process.stdin)枚举所有属性,包括一个标记的属性fd,这当然是第一个参数的名称fs.readSync()
Enjoy! :D
享受!:D
回答by mklement0
An updated version of Marcus Pope's answer that works as of node.js v0.10.4:
从 node.js v0.10.4 开始工作的 Marcus Pope 答案的更新版本:
Please note:
请注意:
- In general, node's stream interfacesare still in flux(pun half-intended) and are still classified as
2 - Unstableas ofnode.js v0.10.4. - Different platforms behave slightly differently; I've looked at
OS X 10.8.3andWindows 7: the major difference is: synchronouslyreading interactivestdin input (by typing into the terminal line by line) only works on Windows 7.
- 一般情况下,节点的流的接口仍然在磁通(双关语半意)和仍然分类为
2 - Unstable作为的node.js v0.10.4。 - 不同平台的行为略有不同;我看过
OS X 10.8.3和Windows 7:主要区别在于:同步读取交互式标准输入(通过逐行输入终端)仅适用于 Windows 7。
Here's the updated code, reading synchronously from stdin in 256-byte chunks until no more input is available:
这是更新后的代码,从 256 字节块中的 stdin 同步读取,直到没有更多输入可用:
var fs = require('fs');
var BUFSIZE=256;
var buf = new Buffer(BUFSIZE);
var bytesRead;
while (true) { // Loop as long as stdin input is available.
bytesRead = 0;
try {
bytesRead = fs.readSync(process.stdin.fd, buf, 0, BUFSIZE);
} catch (e) {
if (e.code === 'EAGAIN') { // 'resource temporarily unavailable'
// Happens on OS X 10.8.3 (not Windows 7!), if there's no
// stdin input - typically when invoking a script without any
// input (for interactive stdin input).
// If you were to just continue, you'd create a tight loop.
throw 'ERROR: interactive stdin input not supported.';
} else if (e.code === 'EOF') {
// Happens on Windows 7, but not OS X 10.8.3:
// simply signals the end of *piped* stdin input.
break;
}
throw e; // unexpected exception
}
if (bytesRead === 0) {
// No more stdin input available.
// OS X 10.8.3: regardless of input method, this is how the end
// of input is signaled.
// Windows 7: this is how the end of input is signaled for
// *interactive* stdin input.
break;
}
// Process the chunk read.
console.log('Bytes read: %s; content:\n%s', bytesRead, buf.toString(null, 0, bytesRead));
}
回答by Nate Ferrero
I found a library that should be able to accomplish what you need: https://github.com/anseki/readline-sync
我找到了一个应该能够完成你需要的库:https: //github.com/anseki/readline-sync
回答by James Wright
Important:I've just been informed by a Node.js contributor that .fdis undocumented and serves as a means for internal debugging purposes. Therefore, one's code should not reference this, and should manually open the file descriptor with fs.open/openSync.
重要提示:我刚刚收到一位.fd未记录的 Node.js 贡献者的通知,该贡献者用作内部调试目的的手段。因此,一个人的代码不应该引用这个,而应该手动打开文件描述符fs.open/openSync。
In Node.js 6, it's also worth noting that creating an instance of Buffervia its constructor with newis deprecated, due to its unsafe nature. One should use Buffer.allocinstead:
在 Node.js 6 中,还值得注意的是,由于其不安全的性质,不推荐使用Buffer通过其构造函数创建的实例new。应该使用Buffer.alloc:
'use strict';
const fs = require('fs');
// small because I'm only reading a few bytes
const BUFFER_LENGTH = 8;
const stdin = fs.openSync('/dev/stdin', 'rs');
const buffer = Buffer.alloc(BUFFER_LENGTH);
fs.readSync(stdin, buffer, 0, BUFFER_LENGTH);
console.log(buffer.toString());
fs.closeSync(stdin);
Also, one should only open and close the file descriptor when necessary; doing this every time one wishes to read from stdin results in unnecessary overhead.
此外,应该只在必要时打开和关闭文件描述符;每次希望从 stdin 读取时都这样做会导致不必要的开销。
回答by exebook
function read_stdinSync() {
var b = new Buffer(1024)
var data = ''
while (true) {
var n = fs.readSync(process.stdin.fd, b, 0, b.length)
if (!n) break
data += b.toString(null, 0, n)
}
return data
}
回答by anshul
Here is the implementation with `async await`. In the below code, the input is taken from standard input and after receiving data the standard input is stopped waiting for data by using `process.stdin.pause();`.
这是使用“async await”的实现。在下面的代码中,输入是从标准输入中获取的,在接收到数据后,标准输入通过使用 `process.stdin.pause();` 停止等待数据。
process.stdin.setEncoding('utf8');
// This function reads only one line on console synchronously. After pressing `enter` key the console will stop listening for data.
function readlineSync() {
return new Promise((resolve, reject) => {
process.stdin.resume();
process.stdin.on('data', function (data) {
process.stdin.pause(); // stops after one line reads
resolve(data);
});
});
}
// entry point
async function main() {
let inputLine1 = await readlineSync();
console.log('inputLine1 = ', inputLine1);
let inputLine2 = await readlineSync();
console.log('inputLine2 = ', inputLine2);
console.log('bye');
}
main();
回答by vadzim
I used this workaround on node 0.10.24/linux:
我在节点 0.10.24/linux 上使用了这个解决方法:
var fs = require("fs")
var fd = fs.openSync("/dev/stdin", "rs")
fs.readSync(fd, new Buffer(1), 0, 1)
fs.closeSync(fd)
This code waits for pressing ENTER. It reads one character from line, if user enters it before pressing ENTER. Other characters will be remained in the console buffer and will be read on subsequent calls to readSync.
此代码等待按 ENTER。如果用户在按 ENTER 之前输入它,它会从行中读取一个字符。其他字符将保留在控制台缓冲区中,并将在后续调用 readSync 时读取。
回答by user3479450
The following code reads sync from stdin. Input is read up until a newline / enter key. The function returns a string of the input with line feeds (\n) and carriage returns (\r) discarded. This should be compatible with Windows, Linux, and Mac OSX. Added conditional call to Buffer.alloc (new Buffer(size) is currently deprecated, but some older versions lack Buffer.alloc.
以下代码从标准输入读取同步。读取输入直到换行/回车键。该函数返回输入的字符串,其中舍弃换行符 (\n) 和回车符 (\r)。这应该与 Windows、Linux 和 Mac OSX 兼容。添加了对 Buffer.alloc 的条件调用(新的 Buffer(size) 目前已弃用,但一些旧版本缺少 Buffer.alloc。
function prompt(){
var fs = require("fs");
var rtnval = "";
var buffer = Buffer.alloc ? Buffer.alloc(1) : new Buffer(1);
for(;;){
fs.readSync(0, buffer, 0, 1); //0 is fd for stdin
if(buffer[0] === 10){ //LF \n return on line feed
break;
}else if(buffer[0] !== 13){ //CR \r skip carriage return
rtnval += new String(buffer);
}
}
return rtnval;
}

