将所有文本从标准输入读取到字符串

问题描述 投票:0回答:5

我正在用 Node.js 编写一个程序,(在某些情况下)想要充当一个简单的过滤器:从 stdin 读取所有内容(直到文件末尾),进行一些处理,将结果写入 stdout。

如何执行“从标准输入读取所有内容”部分?到目前为止,我找到的最接近的解决方案似乎要么从控制台一次只适用于一行,要么仅在 stdin 是文件而不是管道时才有效。

node.js stdin synchronous
5个回答
95
投票

我的这个样板很像上面评论中描述的解决方案——在顶层提供它,因为这是最简单的方法,而且不应该只出现在评论中。

var fs = require('fs');
var data = fs.readFileSync(0, 'utf-8');
// data is a string containing the file's contents

42
投票

我在 Node 11+ 中使用以下内容

 async function read(stream) {
   const chunks = [];
   for await (const chunk of stream) chunks.push(chunk); 
   return Buffer.concat(chunks).toString('utf8');
 }

用途:

const input = await read(process.stdin);

33
投票

如果您使用的是 Linux,则不需要第 3 方软件包。当然,考虑你的性能需求,但是这两行可以工作:

const fs = require("fs");
const data = fs.readFileSync("/dev/stdin", "utf-8");

Jan 在下面的评论中指出,更便携的解决方案是使用

0
,因为这是 POSIX 标准。所以,你可以简单地使用:

const fs = require("fs");
const data = fs.readFileSync(0, "utf-8");

data
现在是一个包含来自 stdin 的数据的字符串,解释为 utf 8


13
投票

get-stdin 就可以了。


在问题的字里行间阅读一些注释。

既然您将问题标记为“同步”,我只会注意到 stdin 在 Node.js 中仅是异步的。上面的库是最简单的。它将把整个输入作为字符串或缓冲区处理。

如果可能,以流式传输方式编写程序是最好的,但有些用例对于流式传输是可行的(即字数统计),而有些用例则不可行(即反转输入)。

此外,“控制台一次一行”是终端缓冲您的击键的产物。如果您想要一些“对不起,我问了”级别的详细信息,请查看令人惊叹的TTY Demystified


3
投票

除了@Patrick Narkinsky 的解决方案之外,我还没有看到真正同步的解决方案。但是 @Patrick Narkinsky 的答案在 Windows 上不起作用。 似乎是一个 node.js 错误。如果你想了解详细信息,请随意进入这个 github issues 的兔子洞,但我读了一个小时后就放弃了。

  1. https://github.com/aws/aws-cdk/issues/11314此处报告的问题
  2. https://github.com/nodejs/node/issues/35997 该库的贡献者创建了一个节点问题
  3. https://github.com/libuv/libuv/pull/3053nodejs 贡献者提交了带有修复程序的 PR(?)(尚未合并)

我无法在那里找到解决方法(我可能掩盖了它),但是我无意中找到了问题的解决方案。它不漂亮,但很有效。由于该链接仅显示如何记录进度,因此我必须根据自己的需要对其进行修改:

import fs from 'fs';
const BUFSIZE = 256;
const buf = Buffer.alloc(BUFSIZE);
let bytesRead;
let stdin = '';

export function stdinToString(): string {
  do {
    // Loop as long as stdin input is available.
    bytesRead = 0;
    try {
      bytesRead = fs.readSync(process.stdin.fd, buf, 0, BUFSIZE, null);
    } 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.
    stdin += buf.toString(undefined, 0, bytesRead);
  } while (bytesRead > 0);

  return stdin;
}

我已经编程十多年了,这是第一次

do while
让我的代码更干净:)如果没有它,如果没有标准输入数据存在,这个函数就会挂起——有人可能会说这是代码中的一个错误该链接的。

这回答了最初的问题并且适用于所有操作系统。

© www.soinside.com 2019 - 2024. All rights reserved.