I'm building a node js app(for learning) where i'm logging each operation into a file called log.txt
The logger module has the following code :
var fs = require('fs');
function write(data,filename)
{
var entry = 'Time: '+new Date();
if(filename !=null || filename != undefined) entry = entry+'\n\tFile: '+filename;
if(data !=null || data != undefined) entry = entry+'\n\tMessage: '+data;
entry = entry+'\n';
fs.appendFile('./log.txt',entry,function(err){
if(err){console.log('Log NOT Appended with data:\n\t'+entry);}
else{console.log('Log Appended with data:\n\t'+entry);}
});
}
exports.write = write;
now in my app.js i'm requiring it as :
var logger = require('./logger');
var fs = require('fs');
function ReadFile()
{
var data = fs.readFileSync('./config.txt');
if(data==null)
logger.write("Config data not found");
else
logger.write(data,"app.js");
}
ReadFile();
This throws me back an error saying :
Object #<Object> has no method 'appendFile'
However this worked fine earlier on a different pc, I noticed this when tried to run my
app on my system.
This was a problem with the version, i was using v0.6.12 which did not have that method, i upgraded to v0.10.0 which solved it, thanks to michaelt for pointing it out.
Related
I tried searching . How do i do it? I'm create html and i want to read .ini file by javascript on the client Not in the server.
I copy code from javascript parser for a string which contains .ini data
error Uncaught ReferenceError: require is not defined var fs = require('fs')
function parseINIString() {
var fs = require('fs')
var data = fs.readFileSync('C:\\test.ini', 'utf8');
var regex = {
section: /^\s*\[\s*([^\]]*)\s*\]\s*$/,
param: /^\s*([\w\.\-\_]+)\s*=\s*(.*?)\s*$/,
comment: /^\s*;.*$/
};
var value = {};
var lines = data.split(/\r\n|\r|\n/);
var section = null;
alert(lines);
for (x = 0; x < lines.length; x++) {
if (regex.comment.test(lines[x])) {
return;
} else if (regex.param.test(lines[x])) {
var match = lines[x].match(regex.param);
if (section) {
value[section][match[1]] = match[2];
} else {
value[match[1]] = match[2];
}
} else if (regex.section.test(lines[x])) {
var match = lines[x].match(regex.section);
value[match[1]] = {};
section = match[1];
} else if (lines.length == 0 && section) {//changed line to lines to fix bug.
section = null;
};
}
return value;
}
Let's say the javascript running in a browser is so called 'client script'. There are lots of limitation while writing client script, one of them is that it's not allowed to visit the user file on disk. This is to prevent any injected hacker script from reading private data. And the explicit error you see is about the new key word 'require' which is well known as 'commonjs' module which is introduced by Nodejs usually. The 'fs' is one of the internal module of Nodejs as well.
So if you still consist using client script to get the job done, you have to rewrite the script, not 'require' the 'fs' module. And use the file reader to get the content of a file object, which is generated by a file input usually.
A detailed introduction about how to read local files.
I have written small code to get files filtered by extension. And my point of view logic is fine but I am unable to point out why I am not getting expected output.
Please have a look.
CODE
var fs = require('fs')
var path = require('path')
path_name = process.argv[2]
ext_name = "."+process.argv[3]
var filter_function = function ( path_name,exthide_name,callback) {
fs.readdir(dirpath,function(err,list) {
if(err) return console.error(err)
for ( var i in list) {
if(path.extname(list[i]) == ext_name)
console.log(list[i])
}
})
}
module.exports=filter_function
Output :
linuxmen#linuxmen-fresh:~/test/test1$ node ownModuleNode.js /home/linuxmen/test/test1/ js
linuxmen#linuxmen-fresh:~/test/test1$
But I have so many files with js extension in that directory.
Proof:
linuxmen#linuxmen-fresh:~/test/test1$ ls *js
check_mod1.js ex1.js ex2.js ex3.js ex4.js ex5.js ex6.js ex7.js ex8.js filter.js filter_use.js modse.js ownModuleNode.js se.js use_mod1.js using_module.js
Could please help , what I am missing.
Update - 1 : I am using above code a module file and calling it here.
File using above code
var mymodule = require('./ownModuleNode')
mymodule.filter_function(process.argv[2],process.argv[3])
Update 2 :
var fs = require('fs')
var path = require('path')
path_name = process.argv[2]
ext_name = "."+process.argv[3]
console.log("path_name :",path_name,"extname:",ext_name)
var filter_function = function ( path_name,ext_name,callback) {
fs.readdir(path_name,function(err,list) {
if (err) console.error(err)
console.log(list)
for ( var i in list) {
if(path.extname(list[i]) == ext_name)
console.log(list[i])
}
})
}
module.exports=filter_function
Output:
linuxmen#linuxmen-fresh:~/test/test1$ node ownModuleNode.js /home/linuxmen/test/test1/ js
pathanme : /home/linuxmen/test/test1/ extname: .js
Thank you.
It looks like you are exporting the function directly. When you require() it, you just getting the function. You'll need to use your module in your application. Put this in 'app.js' in the same dir as ownModuleNode.js:
var filterFunction = require('./ownModuleNode');
filterFunction(process.argv[2], process.argv[3]);
Then call it with:
node app ~/Documents/dev/project .js
Outputs:
app.js
ownModuleNode.js
Note that when you pass the extension, you need the preceding dot because path.extname() returns the dot.
Below is the Node.js Script. It downloads the images contained in a div. The loop works fine for 9.86% that is upto id = 36. When id > 36 it exits the loop. I am using the node 0.12 version. The loop needs to run 365 times before its completion. I am usign the method of recursive callback.
Code:
//Required modules
var fs = require('fs'),
cheerio = require('cheerio'),
request = require('request');
//Default Variables
var baseURI = 'http://www.website/';
var year = 2013;
var id = 1;
var savePath = process.argv[2];
//Download Function
var download = function(uri, filename, callback){
request({ uri: uri }, function(err, res, body){
var $ = cheerio.load(body);
var imgDiv = $('#img-wallpaper').children()['0'];
if(err)
console.err(err);
if(typeof imgDiv !== 'undefined') {
request(imgDiv.attribs.src).pipe(fs.createWriteStream(filename)).on('close', callback);}
});
};
//Main Function
console.log("Downloading . . .");
// Loop function to create a recursive effect
(function loop(){
download(baseURI+year+'/'+id+'/wallpaper/', savePath+id+'.jpg',
function(){
console.log(((id/365)*100).toFixed(2)+'% completed');
if(id == 330)
year = "2014";
if(((id/365)*100) != 100){
id=id+1;
loop();}
});
})(1)
Do I understand correctly that if you set the starting value for the id more than 35 (36?) the script is not downloaded any images?
Test the script on the fixed uri and on the fixed image by changing only the variables. Script is expected to work out? If this is the case:
Or not called callback for body request
Or a false condition typeof imgDiv !== 'undefined'
Or not called callback for request image
Thus, when an error in one of these points the script stops working. It is necessary to change the severity of conditions.
As #stdob said, The error was caused due to
Or a false condition typeof imgDiv !== 'undefined'
Though the answer is not the right way to overcome the error, it is more of an hack type. It ignores the error and continues the script!
if(typeof imgDiv !== 'undefined') {
request(imgDiv.attribs.src).pipe(fs.createWriteStream(filename)).on('close', callback);
}
else{
id++;
request(uri).pipe(fs.createWriteStream(filename)).on('close', callback);
}
Ok, i am just starting to learn node.js and i am having a little difficulty getting a good grasp on the async nature of it and when/how to use callbacks to get data passed along like i need it.
The concept of what i am trying to build is this. I have a small node.js app that uses the FS package - defined as var fs = require("fs"). The app is responding to localhost:4000 right now. When i hit that url, the app will use fs.readdir() to get all of the virtual host files in the directory that i pass to readdir().
Next, the app loops through those files and parses each one line by line and word by word (quick and dirty for now). I am using fs.readFile() to read the file and then literally doing lines = data.toString().split("\n") and then var words = lines[l].split(" ") to get to the data in the file i need. Each virtual host file looks something like this:
<VirtualHost *:80>
ServerName some-site.local
DocumentRoot "/path/to/the/docroot"
<Directory "/path/to/the/docroot">
Options Indexes FollowSymLinks Includes ExecCGI
AllowOverride All
Require all granted
</Directory>
ErrorLog "logs/some-site.local-error_log"
</VirtualHost>
Here is my main.js file (routes file):
var express = require("express"),
router = express.Router(),
async = require("async"),
directoryReader = require(__dirname + "/../lib/directoryReader");
fileReader = require(__dirname + "/../lib/fileReader");
router.get("/", function(req, res) {
var response = [];
directoryReader.read(function(files) {
async.each(files, function(file, callback) {
fileReader.read(file, function(data) {
if (data.length > 0) {
response.push(data);
}
callback();
});
}, function(err){
if (err) throw err;
res.json(response);
});
});
});
module.exports = router;
My directoryReader.js file:
var fs = require("fs"),
fileReader = require(__dirname + "/../lib/fileReader");
var directoryReader = {
read: function(callback) {
var self = this;
fs.readdir("/etc/apache2/sites-available", function (err, files) {
if (err) throw err;
var output = [];
for(f in files) {
output.push(files[f]);
}
callback(output);
});
}
};
module.exports = directoryReader;
And my fileReader.js file:
var fs = require("fs");
var fileReader = {
read: function(file, callback) {
fs.readFile("/etc/apache2/sites-available/" + file, { encoding: "utf8" }, function (err, data) {
if (err) throw err;
var vHostStats = ["servername", "documentroot", "errorlog"],
lines = data.toString().split("\n"),
output = [];
for(l in lines) {
var words = lines[l].split(" ");
for(w in words) {
if (words[w].toLowerCase() == "<virtualhost") {
var site = {
"servername" : "",
"documentroot" : "",
"errorlog" : "",
"gitbranch" : ""
}
w++;
}
if (vHostStats.indexOf(words[w].toLowerCase()) !== -1) {
var key = words[w].toLowerCase();
w++;
site[key] = words[w];
}
if (words[w].toLowerCase() == "</virtualhost>" && site.documentroot != "") {
w++;
output.push(site);
var cmd = "cd " + site["documentroot"] + " && git rev-parse --abbrev-ref HEAD";
var branch = ...; // get Git branch based on the above command
site["gitbranch"] = branch;
}
}
}
callback(output);
});
}
};
module.exports = fileReader;
All of this code will spit out json. This all works fine, expect for one part. The line in the fileReader.js file:
var branch = ...; // get Git branch based on the above command
I am trying to get this code to run a shell command and get the Git branch based on the document root directory. I then want to take the branch returned and add the value to the gitbranch proptery of the current site object during the loop. Hope this makes sense. I know there are probably questions on SO that cover something similar to this and i have looked at many of them. I fear i am just not educated enough in node.js yet to apply the answers to those SO questions to my particular use case.
Please let me know if there's anything i can add that can help anyoe answer this question. I should note that this app is for personal uses only, so the solution really just has to work, not be super elegant.
UPDATE: (5/1/2015)
Probably not the best solution but i got what i wanted by using the new execSync added to v0.12.x
if (words[w].toLowerCase() == "</virtualhost>" && site.documentroot != "") {
var cmd = "cd " + site["documentroot"] + " && git rev-parse --abbrev-ref HEAD";
var branch = sh(cmd, { encoding: "utf8" });
site["gitbranch"] = branch.toString().trim();
w++;
output.push(site);
}
I am an experienced JavaScript programmer, but am just starting to learn node.js.
Using node, I want to read the contents of a directory, and print out files of only a specific extension. Both the directory and file-extension will be given by command-line arguments.
But, I also want to push myself and explore JavaScript programming concepts as I solve these puzzles, so I wanted to create a File object to store information about a file, and use that to solve the problem.
Becaause of this, my approach is overly-complex, and I know that there are simpler ways of doing this, but I just want an answer which solves my current problem:
Why does node.js throw the following error
this.baseName = /.+(?=\.[^.]+)/.exec(file)[0];
^
TypeError: Cannot read property '0' of null
in this code:
function File(file){
if (file instanceof File) return file;
if (!(this instanceof File)) return new File(file);
if (typeof file !== "string") throw new Error("Useful error." + typeof(file));
this.fullName = file;
/*vvvvvvvvvvvv Important Bit vvvvvvvvvvvvvv*/
this.baseName = /.+(?=\.[^.]+)/.exec(file)[0];
this.extension = /[^.]+(?=$)/.exec(file)[0];
}
File.prototype = {
isOfType: function(ext){
return ext === this.extension;
}
}
var fs = require('fs');
var argv = process.argv;
fs.readdir(argv[2], function(err, list){
var res = list.filter(function(element, index, array){
var file = new File(element);
return file.isOfType(argv[3]);
});
console.log(res);
});
but, in a Chrome js console, it runs fine (with simulated process and fs objects of course).
To me (inexperienced me) it looks like node could be making several mistakes:
Not handling the regex properly (I've done tests and this seems likely)
Using square brackets to find key '0' within object, instead of index 0 within array.
Or I could be making several mistakes:
Not understanding fs.readdir and its necessary callback.
Not understanding possible differences between constructors in JavaScript and Node
Please help, I'd like an answer that solves or explains my current problem, not one that works around it.
Thanks.
Node has a built in way to check for valid files
function File(file){
if (file instanceof File) return file;
if (!(this instanceof File)) return new File(file);
if (typeof file !== "string") throw new Error("Useful error." + typeof(file));
var stat = fs.statSync(file);
if ( stat && stat.isFile() ) {
this.fullName = file;
/*vvvvvvvvvvvv Important Bit vvvvvvvvvvvvvv*/
this.baseName = /.+(?=\.[^.]+)/.exec(file)[0];
this.extension = /[^.]+(?=$)/.exec(file)[0];
}
}
Node also has a built in way to get extensions and path names
var path = require('path');
var basename = path.basename(file);
var extension = path.extname(file);
Why does node.js throw the following error
this.baseName = /.+(?=\.[^.]+)/.exec(file)[0];
^
TypeError: Cannot read property '0' of null
Because file doesn't match the regular expression, and so exec returns null; then you're doing null[0], which throws the exception. That would happen for a name like a or a., for instance, or the . and .. pseudo-directories.
Use the NodeJS debugger or just console.log file` immediately prior, an you'll see the value that's causing trouble.
It's because any file names which don't match your regular expression, such as many directory names (which are included in your list variable), will then return null here:
/.+(?=\.[^.]+)/.exec(file)
so you are trying to do
null[0]
which will not work.
I solved this by simply checking for a period within the file name:
var file = (element.indexOf(".") > -1) ? new File(element) : false;
return (file) ? file.isOfType(argv[3]) : false;
within the filter, so final code resembles:
fs.readdir(argv[2], function(err, list){
var res = list.filter(function(element, index, array){
var file = (element.indexOf(".") > -1) ? new File(element) : false;
return (file) ? file.isOfType(argv[3]) : false;
});
for (var i = 0; i < res.length; console.log(res[i++]));
});