Reading file with Node.js - node.js

I have a problem reading the stats of a file. I have this code:
var fs = require('fs');
process.stdin.setEncoding('utf8');
process.stdin.on('readable', function() {
var chunk = process.stdin.read();
if (chunk !== null) {
var stats =fs.statSync(chunk);
length=stats.size;
console.log(length);
}
});
When I exec this code I get this error:
return binding.stat(pathModule._makeLong(path));
^
Error: ENOENT, no such file or directory 'hello.txt
But the problem is that "hello.txt" actually exists at the same directory¡
I have tried with other files and I always get the same error.
Any ideas?
Thanks¡

The chunk read from the standard input contains a new line in the end, which was conflicting with your call to fs.statSync. Try this:
process.stdin.on('readable', function() {
var chunk = process.stdin.read();
if (chunk !== null && chunk !== '') {
var stats = fs.statSync(chunk.trim()); // trim the input
length=stats.size;
console.log(length);
}
});
Also note that the function will be constantly executed for as long as 'readable' events are triggered. You may wish to terminate the program at some point or anything like that.

Related

Reading file using Node.js "Invalid Encoding" Error

I am creating an application with Node.js and I am trying to read a file called "datalog.txt." I use the "append" function to write to the file:
//Appends buffer data to a given file
function append(filename, buffer) {
let fd = fs.openSync(filename, 'a+');
fs.writeSync(fd, str2ab(buffer));
fs.closeSync(fd);
}
//Converts string to buffer
function str2ab(str) {
var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
var bufView = new Uint16Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
append("datalog.txt","12345");
This seems to work great. However, now I want to use fs.readFileSync to read from the file. I tried using this:
const data = fs.readFileSync('datalog.txt', 'utf16le');
I changed the encoding parameter to all of the encoding types listed in the Node documentation, but all of them resulted in this error:
TypeError: Argument at index 2 is invalid: Invalid encoding
All I want to be able to do is be able to read the data from "datalog.txt." Any help would be greatly appreciated!
NOTE: Once I can read the data of the file, I want to be able to get a list of all the lines of the file.
Encoding and type are an object:
const data = fs.readFileSync('datalog.txt', {encoding:'utf16le'});
Okay, after a few hours of troubleshooting a looking at the docs I figured out a way to do this.
try {
// get metadata on the file (we need the file size)
let fileData = fs.statSync("datalog.txt");
// create ArrayBuffer to hold the file contents
let dataBuffer = new ArrayBuffer(fileData["size"]);
// read the contents of the file into the ArrayBuffer
fs.readSync(fs.openSync("datalog.txt", 'r'), dataBuffer, 0, fileData["size"], 0);
// convert the ArrayBuffer into a string
let data = String.fromCharCode.apply(null, new Uint16Array(dataBuffer));
// split the contents into lines
let dataLines = data.split(/\r?\n/);
// print out each line
dataLines.forEach((line) => {
console.log(line);
});
} catch (err) {
console.error(err);
}
Hope it helps someone else with the same problem!
This works for me:
index.js
const fs = require('fs');
// Write
fs.writeFileSync('./customfile.txt', 'Content_For_Writing');
// Read
const file_content = fs.readFileSync('./customfile.txt', {encoding:'utf8'}).toString();
console.log(file_content);
node index.js
Output:
Content_For_Writing
Process finished with exit code 0

Renaming multiple files asyncroniosly causing error in Node.js

I am trying to rename a bunch of pre-generated testing files (1000+) asynchronously in Node.js.
The code looks like the following:
const fs = require('fs')
const { each } = require('async')
each(files, file => {
let newfile = 'new' + file
fs.rename(file, newfile, err => {
err ? console.log(err) : console.log('renamed')
}
})
This leads to following error:
Uncaught Error: ENOENT: no such file or directory, lstat '8d3320e35d22772f'
at fs.lstatSync (fs.js:902:18)
at Object.fs.lstatSync
It's not async module issue, since replacing each with native forEach leads to the same error. Also, there are no issues when using synchronous version of rename fs.renameSync.
I think it's trying to move some file twice or so but can't figure where exactly mistake is. Made this assumption, because all files have been already renamed successfully and very likely error generated afterward. Can someone advice what causing such behavior?
My bad. Just in case someone curious, this error came from following underlying function:
function rmDir(dir) {
var list = fs.readdirSync(dir);
for(var i = 0; i < list.length; i++) {
var dirOrFile = path.join(dir, list[i]);
var stat = fs.lstatSync(dirOrFile);
if(dirOrFile == "." || dirOrFile == "..") {
// pass these files
} else if (stat.isDirectory()) {
// rmdir recursively
rmDir(dirOrFile);
}
// else { fs.unlinkSync(dirOrFile) } // rm fiilename
}
fs.rmdirSync(dir);
}

How to deal with missing file when adding N number of files to NodeJs Archiver

I'm adding a series of files to zip using Archiver, but in the case that a file is missing, say if was deleted or moved, it obviously causes a problem. But I'm not able to get around this problem.
My current code is like so:
for (var i=0; i<receivedIds.length; i++) {
var filePath = './public/pdf/letter-pdfs/'+receivedIds[i]+'.pdf';
console.log(filePath);
try {
pdfStream = fs.createReadStream(filePath);
archive.append(pdfStream, {name: receivedIds[i]+'.pdf'});
} catch(e) {
console.error(e);
}
}
Every time I try to wrap the append in a stream event like so:
pdfStream.on('readable', function() {
archive.append(pdfStream, {name: receivedIds[i]+'.pdf'});
});
The error is caught but the Archiver just outputs some empty file, even though some of the files do exist. How can I update this to append the files that do exist, and simply ignore the ones that don't?
Simply make sure that the file exists before reading it into the archive:
for (var i=0; i<receivedIds.length; i++) {
var filePath = './public/pdf/letter-pdfs/'+receivedIds[i]+'.pdf';
console.log(filePath);
try {
// will throw if it does not exist
// alternatively, use fs.statSync or an async version of the two
fs.accessSync(filePath);
pdfStream = fs.createReadStream(filePath);
archive.append(pdfStream, {name: receivedIds[i]+'.pdf'});
} catch(e) {
console.error(e);
}
}
This way the lack of a file is detected before the archiver attempts to read from an invalid source.

Write a line into a .txt file with Node.js

I want to use Node.js to create a simple logging system which prints a line before the past line into a .txt file. However, I don't know how the file system functionality from Node.js works.
Can someone explain it?
Inserting data into the middle of a text file is not a simple task. If possible, you should append it to the end of your file.
The easiest way to append data some text file is to use build-in fs.appendFile(filename, data[, options], callback) function from fs module:
var fs = require('fs')
fs.appendFile('log.txt', 'new data', function (err) {
if (err) {
// append failed
} else {
// done
}
})
But if you want to write data to log file several times, then it'll be best to use fs.createWriteStream(path[, options]) function instead:
var fs = require('fs')
var logger = fs.createWriteStream('log.txt', {
flags: 'a' // 'a' means appending (old data will be preserved)
})
logger.write('some data') // append string to your file
logger.write('more data') // again
logger.write('and more') // again
Node will keep appending new data to your file every time you'll call .write, until your application will be closed, or until you'll manually close the stream calling .end:
logger.end() // close string
Note that logger.write in the above example does not write to a new line. To write data to a new line:
var writeLine = (line) => logger.write(`\n${line}`);
writeLine('Data written to a new line');
Simply use fs module and something like this:
fs.appendFile('server.log', 'string to append', function (err) {
if (err) return console.log(err);
console.log('Appended!');
});
Step 1
If you have a small file
Read all the file data in to memory
Step 2
Convert file data string into Array
Step 3
Search the array to find a location where you want to insert the text
Step 4
Once you have the location insert your text
yourArray.splice(index,0,"new added test");
Step 5
convert your array to string
yourArray.join("");
Step 6
write your file like so
fs.createWriteStream(yourArray);
This is not advised if your file is too big
I created a log file which prints data into text file using "Winston" logger. The source code is here below,
const { createLogger, format, transports } = require('winston');
var fs = require('fs')
var logger = fs.createWriteStream('Data Log.txt', {
flags: 'a'
})
const os = require('os');
var sleep = require('system-sleep');
var endOfLine = require('os').EOL;
var t = ' ';
var s = ' ';
var q = ' ';
var array1=[];
var array2=[];
var array3=[];
var array4=[];
array1[0] = 78;
array1[1] = 56;
array1[2] = 24;
array1[3] = 34;
for (var n=0;n<4;n++)
{
array2[n]=array1[n].toString();
}
for (var k=0;k<4;k++)
{
array3[k]=Buffer.from(' ');
}
for (var a=0;a<4;a++)
{
array4[a]=Buffer.from(array2[a]);
}
for (m=0;m<4;m++)
{
array4[m].copy(array3[m],0);
}
logger.write('Date'+q);
logger.write('Time'+(q+' '))
logger.write('Data 01'+t);
logger.write('Data 02'+t);
logger.write('Data 03'+t);
logger.write('Data 04'+t)
logger.write(endOfLine);
logger.write(endOfLine);
function mydata() //user defined function
{
logger.write(datechar+s);
logger.write(timechar+s);
for ( n = 0; n < 4; n++)
{
logger.write(array3[n]);
}
logger.write(endOfLine);
}
var now = new Date();
var dateFormat = require('dateformat');
var date = dateFormat(now,"isoDate");
var time = dateFormat(now, "h:MM:ss TT ");
var datechar = date.toString();
var timechar = time.toString();
mydata();
sleep(5*1000);

URL query is undefined when file exists on disk, but not otherwise

This is the simplified version of what I have, but basically the same.
var url_parts = url.parse(req.url, true);
var pathname = url_parts.pathname;
var query = url_parts.query;
var datapath = "data_";
if(query.sort !== undefined)
datapath += query.sort + ".json";
var file = fs.readFile(datapath, function(err,data) {
if(err) throw err;
jsondata = data.toString();
});
This works fine when the file does not exist in the directory. For example, calling http://localhost:12035/sort=date works fine if there is no "data_date.json". However, if that file does exist in the directory, "data_undefined.json" is used instead. Why is this? I have tried all kinds of workarounds to try and narrow it down (ie take a substring of just querystring.stringify(query) ) to no avail...
You should really be checking if query.sort exists, because if I get http://localhost:12035/ query.sort will return "undefined".

Resources