سؤال

هل من الممكن القراءة بشكل متزامن من 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);
});

الآن يمكنني قراءة الخط في وقت من Stdin. ايام سعيدة.

نصائح أخرى

هل جربت:

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

ومع ذلك ، سوف ينتظر قراءة الملف بأكمله ، ولن يعود على n مثل scanf أو cin.

بعد العبث بهذا الأمر قليلاً ، وجدت الإجابة:

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

ستكون الاستجابة عبارة عن صفيف مع فهسين ، الأول هو البيانات التي تم كتابتها في وحدة التحكم والثاني هو طول البيانات بما في ذلك الحرف الجديد.

كان من السهل جدًا تحديد متى console.log(process.stdin) التي تعدد جميع الخصائص بما في ذلك واحدة تحمل علامة fd وهو بالطبع اسم المعلمة الأولى ل fs.readSync()

يتمتع! :د

نسخة محدثة من إجابة ماركوس بوب يعمل اعتبارًا من node.js v0.10.4:

يرجى الملاحظة:

  • على العموم، عقدة دفق واجهات لا تزال في حالة تدفق (التورية نصف المقصودة) وما زالت مصنفة على أنها 2 - Unstable اعتبارا من node.js v0.10.4.
  • منصات مختلفة تتصرف بشكل مختلف قليلاً ؛ لقد نظرت إلى OS X 10.8.3 و Windows 7: الفرق الرئيسي هو: بشكل متزامن قراءة تفاعلي إدخال stdin (عن طريق الكتابة في الخط الطرفي تلو الآخر) يعمل فقط على Windows 7.

إليك الرمز المحدث ، القراءة بشكل متزامن من stdin في قطع 256 بايت حتى لا تتوفر إدخال مزيد من الإدخال:

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

مهم: لقد أبلغت للتو من قبل مساهم Node.JS .fd غير موثق ويعمل كوسيلة لأغراض التصحيح الداخلي. لذلك ، يجب ألا يشير رمز الفرد إلى هذا ، ويجب أن يفتح واصف الملف يدويًا fs.open/openSync.

في 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);

أيضا ، ينبغي للمرء فتح وإغلاق واصف الملف عند الضرورة ؛ القيام بذلك في كل مرة يرغب المرء في القراءة من stdin إلى النفقات العامة غير الضرورية.

هنا هو التنفيذ مع "Async في انتظار". في الكود أدناه ، يتم أخذ الإدخال من الإدخال القياسي وبعد استلام البيانات ، يتم إيقاف الإدخال القياسي في انتظار البيانات باستخدام `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();

لقد كتبت وحدة إضافية صغيرة C ++ تجعل القراءة المتزامنة على لوحة المفاتيح (https://npmjs.org/package/kbd).

لقد استخدمت هذا الحل على العقدة 0.10.24/لينكس:

var fs = require("fs")
var fd = fs.openSync("/dev/stdin", "rs")
fs.readSync(fd, new Buffer(1), 0, 1)
fs.closeSync(fd)

هذا الرمز ينتظر الضغط على إدخال. يقرأ حرفًا واحدًا من السطر ، إذا كان المستخدم يدخله قبل الضغط على Enter. سيتم البقاء أحرفًا أخرى في المخزن المؤقت لوحدة التحكم وسيتم قراءتها على المكالمات اللاحقة إلى 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
}

انا كتبت هذا وحدة لقراءة سطر واحد في وقت واحد من ملف أو stdin. تم تسمية الوحدة النمطية line-reader الذي يكشف ES6 *Generator function للتكرار على خط واحد في وقت واحد. فيما يلي عينة رمز (في TypeScript) من readMe.md.

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

بصرف النظر عن الكود أعلاه ، يمكنك أيضًا إلقاء نظرة على src > tests مجلد في الريبو.

ملحوظة:-
قارئ الخط لا تقرأ الوحدة النمطية جميع الأشياء في الذاكرة بدلاً من ذلك ، فهي تستخدم وظيفة المولد لإنشاء خطوط غير متزامنة أو مزامنة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top