node.js:从标准input读取同步?

是否有可能从stdin同步读取node.js? 因为我正在JavaScript中编写一个JavaScript编译器(仅仅为了好玩)。 Brainfuck支持需要同步实现的读取操作。

我试过这个:

const fs = require('fs'); var c = fs.readSync(0,1,null,'utf-8'); console.log('character: '+c+' ('+c.charCodeAt(0)+')'); 

但是这只产生这个输出:

 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 

我不知道什么时候出现,但这是一个有益的步骤: 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); }); 

现在我可以从标准input一次读取。 快乐的时光。

你有没有尝试过:

 fs=require('fs'); console.log(fs.readFileSync('/dev/stdin').toString()); 

但是,它将等待ENTIRE文件被读入,并且不会像\ scanf或cin \ n那样返回。

在摆弄这个之后,我find了答案:

 process.stdin.resume(); var fs = require('fs'); var response = fs.readSync(process.stdin.fd, 100, 0, "utf8"); process.stdin.pause(); 

响应将是一个有两个索引的数组,第一个是input到控制台的数据,第二个是包含换行符的数据的长度。

确定何时console.log(process.stdin)枚举所有属性,包括一个标记为fd的参数fs.readSync()当然是fs.readSync()的第一个参数的名称fs.readSync()

请享用! :d

Marcus Pope的答案的更新版本, 作为node.js v0.10.4使用

请注意:

  • 一般来说, 节点的stream接口仍然处于stream量 (双关半意)状态,仍然被归类为2 - Unstablenode.js v0.10.4
  • 不同的平台行为略有不同; 我已经看过OS X 10.8.3Windows 7 :主要区别在于: 同步阅读交互式 stdininput(通过在terminal行input) 只适用于Windows 7

这里是更新后的代码, 从标准input以256字节块同步读取,直到没有更多input可用

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

我发现一个应该能够完成你所需要的库: https : //github.com/anseki/readline-sync

我写了一个小小的C ++附加模块,在键盘上进行同步读取( https://npmjs.org/package/kbd )。

重要信息:我刚刚被Node.js贡献者告知, .fd没有logging,可作为内部debugging的手段 。 因此,一个人的代码不应该引用这个,并且应该用fs.open/openSync手动打开fs.open/openSync

在Node.js 6中,还值得注意的是,由于其不安全的特性,不build议使用new构造函数创buildBuffer的实例。 应该使用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); 

另外,必要时只能打开和closures文件描述符; 每当有人希望从标准input读取结果的时候这样做会导致不必要的开销。

我在节点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 ) 

此代码等待按ENTER键。 它从行读取一个字符,如果用户在按ENTER之前input它。 其他字符将保留在控制台缓冲区中,并将在随后调用readSync时读取。

 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 } 

我写了这个模块从文件或标准input一次读取一行。 该模块被命名为line-reader ,它公开一个ES6 *Generator function ,一次迭代一行。 这里是来自readme.md的代码示例(在TypeScript中)。

 import { LineReader } from "line-reader" // FromLine and ToLine are optional arguments const filePathOrStdin = "path-to-file.txt" || process.stdin const FromLine: number = 1 // default is 0 const ToLine: number = 5 // default is Infinity const chunkSizeInBytes = 8 * 1024 // default is 64 * 1024 const list: IterableIterator<string> = LineReader(filePathOrStdin, FromLine, ToLine, chunkSizeInBytes) // Call list.next to iterate over lines in a file list.next() // Iterating using a for..of loop for (const item of list) { console.log(item) } 

除了上面的代码之外,你还可以看看repo中的src > tests文件夹。

注意:-
线阅读器模块不会读取所有东西到内存中,而是使用生成器函数来生成线asynchronous或同步。