I'm having issues with a function that reads a text file line by line. It says the file I'm trying to read does not exist, although it does in the file path I am running node on. What could be the issue??
function insertUsers(auth) {
fs.readFile('emails.txt', function (err, data) {
if (err) throw err;
var person = data.toString().split("\n");
var person = data.toString().split("\n");
for (var i = 0; i < person.length(); i++) {
service.members.insert({
groupKey: 'testgroup#x.com',
resource: {
email: person[i],
role: 'MEMBER',
}
}, (err, res) => {
if (err) { return console.error('The API returned an error:', err.message); }
const user = res.data.member;
if (member.length) {
write_log('Inserted' + email + ' into student group.');
} else {
write_log('Failed to delete ' + email);
}
});
}
});
}
https://i.stack.imgur.com/5UTK6.png and https://i.stack.imgur.com/iVvnA.png
Verify that you're starting your node application from the same location where your file (emails.txt) is. According to your method logic it should be
C:\Users\[]\source\repos\StudentGroups\StudentGroups > node main.js
you can check the current working directory from the code
console.log(process.cwd())
it should be
C:\Users\[]\source\repos\StudentGroups\StudentGroups
Otherwise, modify your code to correctly point to the email.txt or start your application from the correct directory.
This problem was due to how I made emails.txt. The name is "emails.txt", and the file extension is .txt. I changed the file name to "emails", and it worked.
Related
Would like to write data into specific folder using writefile in node js.
I have seen couple of questions in stackoverflow regarding this but none of them worked for me .
For example :
fs.writeFile('./niktoResults/result.txt', 'This is my text', function (err) {
if (err) throw err;
console.log('Results Received');
});
This throws an error "NO SUCH FILE OR DIRECTORY"
Is there any alternative for writing data into specific folder node js ???
Ensure that the directory is available & accessible in the working directory.
In this case, a function like below needs to be called at the start of the application.
function initialize() {
const exists = fs.existsSync('./niktoResults');
if(exists === true) {
return;
}
fs.mkdirSync('./niktoResults')
}
Error caused by directory not existing, create a directory if it does not exist.
function create(text, directory, filename)
{
if (!fs.existsSync(directory)) {
fs.mkdirSync(directory);
console.log('Directory created');
create(text, directory);
} else {
fs.writeFile(`${directory}/${filename}`, `${text}`, function (error) {
if (error) {
throw error;
} else {
console.log('File created');
}
});
}
}
create('Text', 'directory', 'filename.txt');
I updated the function to create the CSV file but now I'm getting an error:
In upload function
internal/streams/legacy.js:57
throw er; // Unhandled stream error in pipe.
^
Error: ENOENT: no such file or directory, open 'C:\Users\shiv\WebstormProjects\slackAPIProject\billingData\CSV\1548963844106output.csv'
var csvFilePath = '';
var JSONFilePath = '';
function sendBillingData(){
var message = '';
axios.get(url, {
params: {
token: myToken
}
}).then(function (response) {
message = response.data;
fields = billingDataFields;
// saveFiles(message, fields, 'billingData/');
saveFilesNew(message, fields, 'billingData/');
var file = fs.createReadStream(__dirname + '/' + csvFilePath); // <--make sure this path is correct
console.log(__dirname + '/' + csvFilePath);
uploadFile(file);
})
.catch(function (error) {
console.log(error);
});
}
The saveFilesNew function is:
function saveFilesNew(message, options, folder){
try {
const passedData = message;
var relevantData='';
if (folder == 'accessLogs/'){
const loginsJSON = message.logins;
relevantData = loginsJSON;
console.log(loginsJSON);
}
if(folder == 'billingData/'){
relevantData = passedData.members;
const profile = passedData.members[0].profile;
}
//Save JSON to the output folder
var date = Date.now();
var directoryPath = folder + 'JSON/' + date + "output";
JSONFilePath = directoryPath + '.json';
fs.writeFileSync(JSONFilePath, JSON.stringify(message, null, 4), function(err) {
if (err) {
console.log(err);
}
});
//parse JSON onto the CSV
const json2csvParser = new Json2csvParser({ fields });
const csv = json2csvParser.parse(relevantData);
// console.log(csv);
//function to process the CSV onto the file
var directoryPath = folder + 'CSV/' + date + "output";
csvFilePath = directoryPath + '.csv';
let data = [];
let columns = {
real_name: 'real_name',
display_name: 'display_name',
email: 'email',
account_type: 'account_type'
};
var id = passedData.members[0].real_name;
console.log(id);
console.log("messageLength is" +Object.keys(message.members).length);
for (var i = 0; i < Object.keys(message.members).length; i++) {
console.log("value of i is" + i);
var display_name = passedData.members[i].profile.display_name;
var real_name = passedData.members[i].profile.real_name_normalized;
var email = passedData.members[i].profile.email;
var account_type = 'undefined';
console.log("name: " + real_name);
if(passedData.members[i].is_owner){
account_type = 'Org Owner';
}
else if(passedData.members[i].is_admin){
account_type = 'Org Admin';
}
else if(passedData.members[i].is_bot){
account_type = 'Bot'
}
else account_type = 'User';
data.push([real_name, display_name, email, account_type]);
}
console.log(data);
stringify(data, { header: true, columns: columns }, (err, output) => {
if (err) throw err;
fs.writeFileSync(csvFilePath, output, function(err) {
console.log(output);
if (err) {
console.log(err);
}
console.log('my.csv saved.');
});
});
} catch (err) {
console.error(err);
}
}
The upload file function is:
function uploadFile(file){
console.log("In upload function");
const form = new FormData();
form.append('token', botToken);
form.append('channels', 'testing');
form.append('file', file);
axios.post('https://slack.com/api/files.upload', form, {
headers: form.getHeaders()
}).then(function (response) {
var serverMessage = response.data;
console.log(serverMessage);
});
}
So I think the error is getting caused because node is trying to upload the file before its being created. I feel like this has something to do with the asynchronous nature of Node.js but I fail to comprehend how to rectify the code. Please let me know how to correct this and mention any improvements to the code structure/design too.
Thanks!
You don't wait for the callback provided to stringify to be executed, and it's where you create the file. (Assuming this stringify function really does acccept a callback.)
Using callbacks (you can make this cleaner with promises and these neat async/await controls, but let's just stick to callbacks here), it should be more like:
function sendBillingData() {
...
// this callback we'll use to know when the file writing is done, and to get the file path
saveFilesNew(message, fields, 'billingData/', function(err, csvFilePathArgument) {
// this we will execute when saveFilesNew calls it, not when saveFilesNew returns, see below
uploadFile(fs.createReadStream(__dirname + '/' + csvFilePathArgument))
});
}
// let's name this callback... "callback".
function saveFilesNew(message, options, folder, callback) {
...
var csvFilePath = ...; // local variable only instead of your global
...
stringify(data, { header: true, columns: columns }, (err, output) => {
if (err) throw err; // or return callbcack(err);
fs.writeFile(csvFilePath , output, function(err) { // NOT writeFileSync, or no callback needed
console.log(output);
if (err) {
console.log(err);
// callback(err); may be a useful approach for error-handling at a higher level
}
console.log('my.csv saved.'); // yes, NOW the CSV is saved, not before this executes! Hence:
callback(null, csvFilePath); // no error, clean process, pass the file path
});
});
console.log("This line is executed before stringify's callback is called!");
return; // implicitly, yes, yet still synchronous and that's why your version crashes
}
Using callbacks that are called only when the expected events happen (a file is done writing, a buffer/string is done transforming...) allows JS to keep executing code in the meantime. And it does keep executing code, so when you need data from an async code, you need to tell JS you need it done before executing your piece.
Also, since you can pass data when calling back (it's just a function), here I could avoid relying on a global csvFilePath. Using higher level variables makes things monolithic, like you could not transfer saveFilesNew to a dedicated file where you keep your toolkit of file-related functions.
Finally, if your global process is like:
function aDayAtTheOffice() {
sendBillingData();
getCoffee();
}
then you don't need to wait for the billing data to be processed before starting making coffee. However, if your boss told you that you could NOT get a coffee until the billing data was settled, then your process would look like:
function aDayAtTheOffice() {
sendBillingData(function (err) {
// if (err) let's do nothing here: you wanted a coffee anyway, right?
getCoffee();
});
}
(Note that callbacks having potential error as first arg and data as second arg is a convention, nothing mandatory.)
IMHO you should read about scope (the argument callback could be accessed at a time where the call to saveFilesNew was already done and forgotten!), and about the asynchronous nature of No... JavaScript. ;) (Sorry, probably not the best links but they contain the meaningful keywords, and then Google is your buddy, your friend, your Big Brother.)
I am trying to find matches in files and parse out the line number and what was the match along with the file name. So far I am able to read the files from the directory / sub directories and then use indexOf() which in this case is not very efficient. The goal would be go through all the files and find matches for the following
.http(
.httpContinue(
$httpUrl(
httpURL
getHttpImageURL(
getHttpURL(
The code I have so far looks like this
var fs = require('fs');
var path = [my directory];
function readFiles(dirname) {
fs.readdir(dirname, function(err, filenames) {
if (err) {
return;
}
filenames.forEach(function(filename) {
if (fs.lstatSync(dirname+'/'+filename).isDirectory() ){
readFiles(dirname+'/'+filename);
};
fs.readFile(dirname+'/'+filename, { encoding: 'utf8' }, function(err, content) {
if (err) {
return;
}
//This is not very effective and I need to check each line for all these possible matches
if (content.indexOf('http(') > -1) {
if(err) {
return console.log(err);
}
console.log(filename);
}
});
});
});
}
readFiles(path);
The challenge I am facing is to read lines and parse line numbers where I found a match and what was the match. Cant figure out how to accomplish that.
You could try this for your if statement
// This should really go somewhere near the top of the file
const wantedStrings = ['.http(',
'.httpContinue(',
'$httpUrl(',
'httpURL',
'getHttpImageURL(',
'getHttpURL('];
if (content.toLowerCase().includes('http')
&& wantedStrings.filter(s => content.includes(s)).length > 0) {
// Don't need another err check here
console.log(filename);
}
So I have the following code
var processed;
fs.readFile(path, 'utf-8', function(err, data) {
processed = false;
//checking if text is in file and setting flag
processed = true;
});
if (processed == true) {
try {
var fname = path.substring(path.lastIndexOf("\\") + 1);
fs.moveSync(path, './processedxml/' + fname, {
overwrite: true
})
} catch (err) {
console.log("Error while moving file to processed folder " + err);
}
}
But I don't get the desired output. Because looks like the readfile is executed by a separate thread and so the value of "processed" is not reliable.
I am not very familiar with nodejs so any help will be greatly appreciated.
Yes, you are right, your executions are performed by different threads.
In this scenario, you'll need to use promises.
You can solve your need easily by using "Promise FS" (you can use any other promise solution anyway).
Your code would be something like the following:
fs = require('promise-fs');
var fname = 'test.txt' ;
var toMove = false ;
fs.readFile('test.txt','utf8')
.then (function (content) {
if(content.indexOf('is VALID') !== -1) {
console.log('pattern found!');
toMove = true ;
}
else { toMove = false
}
return toMove ;
}).
then (function (toMove) {
if(toMove) {
var oldPath = 'test.txt'
var newPath = '/tmp/moved/file.txt'
fs.rename(oldPath, newPath, function (err) {
if (err) throw err
console.log('Successfully renamed - moved!')
}) ;
}
})
.catch (function (err) {
console.log(err);
})
Create a file "test.txt" and add the following contents:
this is text.file contents
token is VALID
The code above will evaluate if "is VALID" is present as content and if it does then it will move the file "test.txt" from your current folder to a new one called "moved" in "/tmp" directory. It will also rename the file as "file.txt" file name.
Hope it helps you.
Regards
It looks like you're shadowing path, trying to use it as a variable and as a node module. The easiest way to make this work is to choose a different variable name for the file and move the processing logic into the callback of fs.readFile.
var path = require('path');
var fs = require('fs-extra');
var file = 'some/file/path/foo.xml';
var text = 'search text';
fs.readFile(file, 'utf-8', function (err, data) {
if (err) {
console.error(err);
} else {
//checking if text is in file and setting flag
if (data.indexOf(text) > -1) {
try {
var fname = path.basename(file);
fs.moveSync(file, './processedxml/' + fname, {
overwrite: true
})
} catch (err) {
console.log("Error while moving file to processed folder " + err);
}
}
}
});
I have a fairly simple script that attempts to read and then parse a JSON file. The JSON is very simple and I am pretty sure it is valid.
{
"foo": "bar"
}
Now, I have been trying to read it with fs.readFile. When read no errors occur and the returned data is a string. The only problem is that the string is empty.
I repeated my code but used fs.readFileSync, this returned the file perfectly using the same path. Both had a utf-8 encoding specified.
It is very simple code, as you can see.
fs.readFile('./some/path/file.json', 'utf8', function(err, data) {
if(!err) {
console.log(data); // Empty string...
}
});
console.log(fs.readFileSync('./some/path/file.json', 'utf8')); // Displays JSON file
Could it be permissions or ownership? I have tried a permission set of 755 and 777 to no avail.
I am running node v0.4.10. Any suggestions to point me in the right direction will be much appreciated. Thanks.
Edit: Here is a block of my actual code. Hopefully this will give you a better idea.
// Make sure the file is okay
fs.stat(file, function(err, stats) {
if(!err && stats.isFile()) {
// It is okay. Now load the file
fs.readFile(file, 'utf-8', function(readErr, data) {
if(!readErr && data) {
// File loaded!
// Now attempt to parse the config
try {
parsedConfig = JSON.parse(data);
self.mergeConfig(parsedConfig);
// The config was loaded and merged
// We can now call the callback
// Pass the error as null
callback.call(self, null);
// Share the news about the new config
self.emit('configLoaded', file, parsedConfig, data);
}
catch(e) {
callback.call(self, new Error(file + ': The config file is not valid JSON.'));
}
}
else {
callback.call(self, new Error(file + ': The config file could not be read.'));
}
});
}
else {
callback.call(self, new Error(file + ': The config file does not exist.'));
}
});
This is pretty weird.
The code looks.
var fs = require('fs');
fs.readFile('./jsonfile', 'utf8', function(err, data) {
if(err) {
console.error(err);
} else {
console.log(data);
parsedConfig = JSON.parse(data);
console.log(parsedConfig);
console.log(parsedConfig.foo);
}
});
Json file:
{
"foo": "bar"
}
output :
$ node test_node3.js
{
"foo": "bar"
}
{ foo: 'bar' }
bar
This is on node 0.4.10 , but i'm pretty sure it should work on all node version.
So why your data is empty ? You should check err in this case (like mine) and post the output if any. If you have no error, you may fill a bug on github