Not reading text in a right way node js - javascript

I am working on a sales tax problem with node js and I am trying to read text from a file input.txt then calculate the taxes and prices as a final output.
I used the function below to read the file input.txt line by line and it's working
var fs = require('fs'),
readline = require('readline');
var rl = readline.createInterface({
input : fs.createReadStream('input.txt'),
output: process.stdout,
terminal: false
})
rl.on('line',function(line){
console.log(line)
})
But the problem is when I tried use the function scanProduct() on that text it didn't work.
This is the whole code
var Cart = require('./src/Cart');
var cart1 = new Cart();
var cart2 = new Cart();
var cart3 = new Cart();
cart1.scanProduct('1 book at 12.49');
cart1.scanProduct('1 music CD at 14.99');
cart1.scanProduct('1 chocolate bar at 0.85');
cart2.scanProduct('1 imported box of chocolates at 10.00');
cart2.scanProduct('1 imported bottle of perfume at 47.50');
// cart3.scanProduct('1 imported bottle of perfume at 27.99');
// cart3.scanProduct('1 bottle of perfume at 18.99');
// cart3.scanProduct('1 packet of headache pills at 9.75');
// cart3.scanProduct('1 box of imported chocolates at 11.25');
var fs = require('fs'),
readline = require('readline');
var rl = readline.createInterface({
input : fs.createReadStream('input.txt'),
output: process.stdout,
terminal: false
})
rl.on('line',function(line){
//console.log(line)
cart3.scanProduct(line)
})
console.log(cart1.bill());
console.log("\n");
console.log(cart2.bill());
console.log("\n");
console.log(cart3.bill());
scanProduct() and bill() are fuction used to calculate taxes and give the final output and it's working in cart1 and car2 that way. When I tried to get text from the file it didn't work.

It fails because reading of a file is an asynchronous operation and cart3.bill()
function is called before cart3.scanProduct(line) function.
You should listen to an 'end' event of a readable stream then call the cart3.bill() function.
Like this:
rl.on('end',function(){
console.log(cart3.bill());
})

Related

How to update in html page during nodejs readline process

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

Array is empty after readline data is pushed

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.

How do I use readline in Node.js to get all input lines into an array?

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' ]

Node.js start reading a file on a specific line

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

Haskell call Node.js file not working

I am trying to write a program in Haskell that takes in the input as a string of sentences, calls a javascript file with that input, and return the output of that javascript file as the output of the Haskell file. Right now, the output of the javascript file is not printed. It is not clear whether javascript file is called or not.
Here is the script in Haskell:
main :: IO ()
main =
do
putStrLn "Give me the paragraphs \n"
paragraphs <- getLine
output <- readCreateProcess (shell "node try2.js") paragraphs
putStrLn output
Script in Node.js. The desired output is toplines:
var lexrank = require('./lexrank');
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('Hi', (answer) => {
var originalText = answer;
var topLines = lexrank.summarize(originalText, 5, function (err, toplines, text) {
if (err) {
console.log(err);
}
rl.write(toplines);
// console.log(toplines);
});
rl.close();
});
I am guessing there is some problem with my way of doing stdin. I am new to Node.js
It took me a really long time but following code works:
Haskell File:
import System.Process
main :: IO ()
main =
do
putStrLn "Give me the paragraphs \n"
paragraphs <- getLine
output <- readCreateProcess (shell "node lexrankReceiver.js") (paragraphs ++ "\n")
putStrLn output
NodeJs File:
// Getting this to work took almost a full day. Javascript gets really freaky
// when using it on terminal.
/* Import necessary modules. */
var lexrank = require('./Lexrank/lexrank.js');
const readline = require('readline');
// var Type = require('type-of-is');
// var utf8 = require('utf8');
// Create readline interface, which needs to be closed in the end.
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
// Set stdin and stdout to be encoded in utf8. Haskell passes string as basic
// 8-bit unsigned integer array. The output also needs to be encoded so that
// Haskell can read them
process.stdin.setEncoding('utf8');
process.stdout.setEncoding('utf8');
// If a string is readable, start reading.
process.stdin.on('readable', () => {
var chunk = process.stdin.read();
if (chunk !== null) {
var originalText = chunk;
var topLines = lexrank.summarize(originalText, 5, function (err, toplines, text) {
if (err) {
console.log(err);
}
// Loop through the result to form a new paragraph consisted of most
// important sentences in ascending order. Had to split the 0 index and
// the rest indices otherwise the first thing in newParagraphs will be
// undefined.
var newParagraphs = (toplines[0])['text'];
for (var i = 1; i < toplines.length; i++) {
newParagraphs += (toplines[i])['text'];
}
console.log(newParagraphs);
});
}
});
// After the output is finished, set end of file.
// TODO: write a handler for end of writing output.
process.stdin.on('end', () => {
process.stdout.write('\n');
});
// It is incredibly important to close readline. Otherwise, input doesn't
// get sent out.
rl.close();
The problem with the Haskell program you have is that paragraphs is not a line of input, just a string, so to fix the issue you can append a newline, something like:
output <- readCreateProcess (shell "node try2.js") $ paragraphs ++ "\n"
To find this issue I tried replacing question with a shim:
rl.question = function(prompt, cb) {
rl.on('line', function(thing) {
console.log(prompt);
cb(thing);
})
}
And that worked, so I knew it was something to do with how question handles stdin. So after this I tried appending a newline and that worked. Which means question requires a 'line' of input, not just any string, unlike on('line'), oddly enough.

Categories