I want to dynamically change the content of a element in my html page during nodejs readline process.
Here is a jsfiddle example to shown the display effect I want to fulfill:
https://jsfiddle.net/09kuyn7v/
But I want to dynamically display lines from my local file, but not from an array defined within the function as in the jsfiddle example.
I have used readline module in my read-file-version clickTest() function:
function clickTest(){
var fs = require('fs');
var lineReader = require('readline').createInterface({
input: fs.createReadStream(filePath)
});
lineReader.on('line', function(line){
document.getElementById("demo").innerHTML += line;
});
}
But when I click the button, the page was just like being freezed and then the lines were displayed simultaneously (not one by one as shown in the jsfiddle example above).
First of all, every time you call that function you do require('readline') and require('fs') so I would move that up the script.
I would suggest two approaches:
Pausing read
var readline = require('readline');
var fs = require('fs');
function clickTest(){
var lineReader = readline.createInterface({
input: fs.createReadStream(filePath)
});
lineReader.on('line', function(line){
// pause emitting of lines...
lineReader.pause();
// write line to dom
document.getElementById("demo").innerHTML += line;
// Resume after some time
setTimeout(function(){
lineReader.resume();
}, 1000);
});
lineReader.on('end', function(){
lineReader.close();
});
}
This approach should read one line, then pause and resume after some time you specify.
Buffering lines
var readline = require('readline');
var fs = require('fs');
var lines = [];
function clickTest(){
var lineReader = readline.createInterface({
input: fs.createReadStream(filePath)
});
lineReader.on('line', function(line){
lines.push(line)
});
lineReader.on('end', function(){
lineReader.close();
printLine(0);
});
}
function printLine(index){
// write line to dom
document.getElementById("demo").innerHTML += lines[index];
if (index < lines.length - 1){
setTimeout(function(){
printLine(index + 1);
}, 1000);
}
}
This approach will save all the lines into an array and then slowly prints them out.
Please note that I haven't got node-webkit to actually test it, so you might find a bug in the code, but it should give you general idea
Related
function readFile(){
var lineReader = require('readline').createInterface({
input: require('fs').createReadStream(FILE_PATH)
});
lineReader.on('line', function (line) {
setTimeout(() => {
console.log("HEYYYYY");
}, 10000);
});
}
Why does this only waits 10 seconds once , and the prints 'hey' ? I want to print hey each 10 seconds but it's not working. No idea why.
Edit: This is going to be repeated by the amount of lines that there are on a file (look at the listener 'line') I need to delay 10s between each line.
I had the same problem and I solved it with the "Example: Read File Stream Line-by-Line" found in: https://nodejs.org/api/readline.html
In your case it would be something like this:
const fs = require('fs');
const readline = require('readline');
async function processLineByLine() {
const fileStream = fs.createReadStream(FILE_PATH);
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
// Note: we use the crlfDelay option to recognize all instances of CR LF
// ('\r\n') in input.txt as a single line break.
for await (const line of rl) {
// Each line in input.txt will be successively available here as `line`.
console.log(`Line from file: ${line}`);
await sleep(10000)
}
}
function sleep(ms){
return new Promise(resolve=>{
setTimeout(resolve,ms)
})
}
This example would print you a line every 10 seconds.
It's not waiting 10 seconds once. its just that each line is read so fast, there's almost not difference in the start time. you can add a variable that increase the delay by 10 seconds in each callback so you each line is print each 10 seconds.
function readFile(){
var delay = 0;
var lineReader = require('readline').createInterface({
input: require('fs').createReadStream(FILE_PATH)
});
lineReader.on('line', function (line) {
delay += 10000;
setTimeout(() => {
console.log("HEYYYYY");
}, 10000+delay);
});
}
I am trying to write a program, where I need to read data from a file line by line synchronously, store values line by line in an array using Array.push(). I am reading the file using the readline npm package. However, when I try to call the array after iterating through the whole file, it shows me an empty array.
var fs = require('fs'),
readline = require('readline'),
stream = require('stream');
var instream = fs.createReadStream('sample.txt');
var outstream = new stream;
outstream.readable = true;
outstream.writable = true;
function printArray(ArrayVar){
console.log(ArrayVar);
}
function AddText(InputStream){
var Text = new Array;
var rl = readline.createInterface({
input: instream,
output: outstream,
terminal: false
});
rl.on('line',function(line){
Text.push(line);
});
return Text;
}
var a = AddText(instream);
printArray(a);
I think I am having a problem because of the asynchronous execution of this code. How can I fix this and print the content of the array in proper order as in the text file?
You need to listen to the close event and then print the array. close will be called once all lines have been read.
rl.on('close', function() {
console.log(Text)
});
Also,
var Text = new Array;
Should be:
var Text = new Array();
or
var Text = [];
You have to wait for the lines to be read before logging the variable(in your case its Text) value.
You must wait for all the lines to be read by listening on close event, or do something in line event itself.
Your code should look something like below
var fs = require('fs'),
readline = require('readline'),
stream = require('stream');
var instream = fs.createReadStream('sample.txt');
var outstream = new stream;
outstream.readable = true;
outstream.writable = true;
function printArray(ArrayVar){
console.log(ArrayVar);
}
function AddText(InputStream){
var Text = new Array;
var rl = readline.createInterface({
input: instream,
output: outstream,
terminal: false
});
rl.on('line',function(line){
Text.push(line);
});
rl.on('close', function(){
printArray(Text)
})
}
var a = AddText(instream);
Also you are not using the parameter InputStream that you are passing to AddText function.
I'd like to create a convenience function that does something like this for the purposes of CodeAbbey:
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
var lines = [];
rl.on('line', (line) => {
lines.push(line);
});
return lines;
However, because of how readline functions as an event handler of course all I get back is an empty array.
How do I get readline to carry out the desired behavior here? Or do I use some other library? I'd rather just use "default" components but if I have to use something else I will.
var lines = [];
rl.on('line', (line) => {
lines.push(line);
}).on('close', () => {
// Do what you need to do with lines here
process.exit(0);
});
As Node.js runs on an event-loop, a lot of the functionality available in many packages, including Readline, are asynchronous. In general you will need to process lines when the close event is emitted.
You may find this very similar resolved question helpful:
node.js: read a text file into an array. (Each line an item in the array.)
Hope this helps!
You'll want to access the lines array on close event:
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
var lines = [];
rl.on('line', (line) => {
lines.push(line);
});
rl.on('close', () => {
console.log(lines);
});
This code will establish the createInterface, and initialize an empty of array lines. At the prompt, when the user hits the enter key it fires the "line" event and adds the previous written line to the lines array. When you close the interface (by killing the process or manually closing in code) it will log out the array.
$ node readlines.js
this is
the second line
third
[ 'this is', 'the second line', 'third' ]
On Node.js we can read a file line by line using the readline module:
var fs = require('fs');
var readline = require('readline');
var rl = readline.createInterface({
input: fs.createReadStream('filepath');
});
rl.on('line', function(line) {
console.log(`Line read: ${line}`);
});
But what if we want to start reading on a specific line number? I know that when we use the createReadStream we can pass in a start parameter. This is explained in the docs:
options can include start and end values to read a range of bytes from the file instead of the entire file.
But here start is one offset in bytes, so it seems complicated to use this to set the starting line.
How can we adapt this approach to start reading a file on a specific line?
You have to read the file from the beginning and count lines and start processing the lines only after you get to a certain line. There is no way to have the file system tell you where a specific line starts.
var fs = require('fs');
var readline = require('readline');
var cntr = 0;
var rl = readline.createInterface({
input: fs.createReadStream('filepath');
});
rl.on('line', function(line) {
if (cntr++ >= 100) {
// only output lines starting with the 100th line
console.log(`Line read: ${line}`);
}
});
I was wondering if it was at all possible to read the very last line of a text file. And then, read the one before that. I can see all the data in the console, but I have no idea how to just display one line.
Currently, I am using fs and byline, to write and read files, respectively.
Use the readline core module instead of byline, and keep track of the current and previous lines when you receive events.
var rl = require('readline').createInterface({
input: require('fs').createReadStream('input.file')
});
var current = "";
var prev = "";
rl.on('line', function (line) {
prev = current;
current = line;
});
rl.on('close', function () {
console.log('Last line:', current);
console.log('Prev line:', prev);
});
Alternatively, just read the whole file into a string and then split it after line breaks.