node.js: readsync من stdin؟
-
26-09-2019 - |
سؤال
هل من الممكن القراءة بشكل متزامن من 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
مجلد في الريبو.
ملحوظة:-
قارئ الخط لا تقرأ الوحدة النمطية جميع الأشياء في الذاكرة بدلاً من ذلك ، فهي تستخدم وظيفة المولد لإنشاء خطوط غير متزامنة أو مزامنة.