NodeJS 某些输入的Stdin读取失败

quhf5bfb  于 2022-12-03  发布在  Node.js
关注(0)|答案(3)|浏览(177)
#!/usr/bin/env node

function stdinReadSync() {
   var b = new Buffer(1024);
   var data = '';

   while (true) {
      var n = require('fs').readSync(process.stdin.fd, b, 0, b.length);
      if (!n) break;
      data += b.toString(null, 0, n);
   }
   return data;
}

var s = stdinReadSync();
console.log(s.length);

上面的代码(取自Stackoverflow)如果你给它输入echocatls,它就能正常工作,但是如果输出curl,它就会失败。

$ echo abc | ./test.js
4

$ ls | ./test.js
1056

$ cat 1.txt | ./test.js
78

$ curl -si wikipedia.org | ./test.js
fs.js:725
  var r = binding.read(fd, buffer, offset, length, position);
                  ^

Error: EAGAIN: resource temporarily unavailable, read
    at Error (native)
    at Object.fs.readSync (fs.js:725:19)
    at stdinReadSync (/home/ya/2up/api/stdinrd.js:8:29)
    at Object.<anonymous> (/home/ya/2up/api/stdinrd.js:15:9)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:456:32)
    at tryModuleLoad (module.js:415:12)
    at Function.Module._load (module.js:407:3)
    at Function.Module.runMain (module.js:575:10)
(23) Failed writing body

为什么?怎么解决?

bz4sfanl

bz4sfanl1#

这是一个有点黑客,但这似乎是工作:

var n = require('fs').readSync(0, b, 0, b.length);

我认为(纯粹是猜测)process.stdin.fd是一个getter,当引用它时,它会将stdin置于非阻塞模式(这是导致错误的原因)。

xxhby3vn

xxhby3vn2#

这是一个从stdin同步阅读的问题,正如我所看到的,有no solution for it和它wouldn't fixed,因为进程.stdin.fd不是公共API的一部分,不应该以任何方式使用。最好使用promisified版本来避免这种错误,并从stdin读取:

function streamToPromise(stream) {
    return new Promise((resolve, reject) => {
        let chunks = [];

        function onData(chunk) {
            chunks.push(chunk);
        };

        function onEnd() {
            unbind();
            resolve(Buffer.concat(chunks));
        };

        function onError(error) {
            unbind();
            reject(error);
        };

        function unbind() {
            stream.removeListener('data', onData);
            stream.removeListener('end', onEnd);
            stream.removeListener('error', onError);
        }

        stream.on('data', onData);
        stream.on('end', onEnd);
        stream.on('error', onError);
    });
}

streamToPromise(process.stdin).then((input) => {
    // Process input
});
yyyllmsg

yyyllmsg3#

EAGAIN表示资源暂时不可用,应重试请求

#!/usr/bin/env node

const fs = require('fs')

function stdinReadSync() {
    const b = Buffer.alloc(1024)
    let data = ''

    while (true) {
        let n = 0

        // Read while EAGAIN
        while (true) {
            try {
                n = fs.readSync(process.stdin.fd, b, 0, b.length)
                break
            } catch (e) {
                if (e.code === 'EAGAIN') {
                    // Sleep 100ms
                    Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 100)
                    continue
                }
                throw e
            }
        }

        if (!n) break
        data += b.toString('utf8', 0, n)
    }

    return data
}

const s = stdinReadSync()
console.log(s.length)

相关问题