I am trying to remove a string from text.txt. text.txt file contains following format of string
text/more/more.txt
text/home.txt
text/more/yoo/yoo.txt
text/about.txt
Now what I am doing is watching a folder and when any of the above listed file, lets say text/about.txt, is deleted then text.txt file should automatically be updated to following
text/more/more.txt
text/home.txt
text/more/yoo/yoo.txt
For this I am using hound module to keep watching for delete event. And replace module to replace deleted path from text.txt file. Below is my code
watcher.on('delete', function(file, stats) {
replace({
regex: /file/g, // file is something like this text/about.txt
replacement: '',
paths: [path + '/text.txt'],
recursive: true,
silent: true,
});
});
But my above code does not remove particular string i.e. file from text.txt file. How can I solve this?
UPDATE
file in above code has this value text/about.txt.
This is a error in semantics, you misinterpreted what happens when you do this:
watcher.on('delete', function(file, stats) {
...
regex: /file/g, // file is something like this text/about.txt
...
}
Here, file in the RegExp object is looking for a string called file, not the actual variable contents of the String object you're passing into the function. Do this instead:
regex: new RegExp(file, 'g'), // file is something like this text/about.txt
See RegExp for more details.
I have updated variable search_content and replace_content to handle special characters also and then using fs module to replace all strings in a file. Also you can run a synchronous loop on a files to replace strings using callbacks.
// Require fs module here.
var search_content = "file";
var replace_content = '';
var source_file_path = '<<source file path where string needs to be replaced>>';
search_content = search_content.replace(/([.?&;*+^$[\]\\(){}|-])/g, "\\$1");//improve
search_content = new RegExp(search_content, "g");
fs.readFile(source_file_path, 'utf8', function (rfErr, rfData) {
if (rfErr) {
// show error
}
var fileData = rfData.toString();
fileData = fileData.replace(search_content, replace_content);
fs.writeFile(source_file_path, fileData, 'utf8', function (wfErr) {
if (wfErr) {
// show error
}
// callback goes from here
});
});
Related
I am trying to parse a YAML file. I was able to parse the file properly but the comments in the YAML file are not getting read. Is there any way to do it? Attaching the parser code and config.json. Also attaching the screenshot of the file and output for reference.
var fs= require('fs');
var path= require('path');
var yaml = require('js-yaml')
var fname= "config.json"
var jPath= path.join(__dirname,"..","ConfigGen","Config",fname);
var jsString= fs.readFileSync(jPath, 'utf8')
// Get path for files from Config file
var tType= "cto" //Get this from input
var pth= JSON.parse(jsString)[tType] //perform error handling
var cType = "jbod" //Get this from input
//Use that path
fs.readdir(pth, function(err,files) {
files.forEach(function(file){
fName= cType+"_"+tType+"_uut.yaml-example";
if(file==fName){
var flContent= fs.readFileSync(path.join(pth,file),"utf8")
// return path.join from here and use the next part in a separate function
var data= yaml.safeLoad(flContent)[0][0]
console.log(data)
for (var index in data){
var prefix = index
for (idx in data[index]){
//console.log(prefix, idx ,data[prefix][idx])
}
}
}
})
})
Reiterating flyx's comment, according to the YAML spec on comments:
Comments are a presentation detail and must not be used to convey content information.
So assuming you're not going to be able to correlate the comments to any adjacent fields, you can just read the whole file as a string and match against any characters after a #
You can read the file and parse with this regex like this:
var { promises: fs } = require('fs');
(async() => {
let path = "./config.yaml"
let file = await fs.readFile(path, "utf8")
let matches = file.matchAll(/#.*/g)
let comments = [...matches].map(m => m[0])
console.log(comments)
})()
If you have a yaml file that looks like this:
# block comment
env: dev
prop: value # inline comment
It will log the following:
[ '# block comment', '# inline comment' ]
Newbie in node and express
I am taking user input from html-form and trying to append or push it in a .json file.
I have used jsonfile npm-package but it is not coming in a array format of json
code for appending-
var express = require('express');
var app = express();
//jade --> ejs -->html
app.engine('html', require('ejs').renderFile);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'html');
var jsonfile = require('jsonfile');
var file = './userdata.json'
//trying to write via form to json
app.post('/gettingdata', function(req, res) {
var user_id = req.body.usrid;
var token = req.body.usrphone;
var geo = req.body.usrdata;
//start writing
var obj = { name: user_id , phone: token, adress: geo }
jsonfile.writeFileSync(file, obj, {flag: 'a'});
//default
//res.send(user_id + ' ' + token + ' ' + geo);
});
html -
<body>
<form action="/gettingdata" method="post">
Name:<input type="text" name="usrid" /><br>
Phone:<input type="text" name="usrphone" /><br>
RData:<input type=="text" name="usrdata" /><br>
<input type="submit" value="Submit" >
</form>
</body>
json appearing as-
{"name":"name1","phone":"8989898989","adress":"random1"}
{"name":"name1","phone":"767656568","adress":"randomdata1"}
{"name":"name1","phone":"767656568","adress":"randomdata1"}
there are no commas appearing between objects and no square brackets. I need them to be able to make parsing possible, so that I can dynamically edit and delete data from my front-end later.
Suggest any link,method or npm package to do so.If question repeated share the link of that too
I will expand on Shil's answer with some code:
// 1. Read the existing file
fs.readFile(file, (err, data) => {
if (err && err.code === "ENOENT") {
// But the file might not yet exist. If so, just write the object and bail
return fs.writeFile(file, JSON.stringify([obj]), error => console.error);
}
else if (err) {
// Some other error
console.error(err);
}
// 2. Otherwise, get its JSON content
else {
try {
const fileData = JSON.parse(data);
// 3. Append the object you want
fileData.push(obj);
//4. Write the file back out
return fs.writeFile(file, JSON.stringify(fileData), error => console.error)
} catch(exception) {
console.error(exception);
}
}
});
This is just a quick, illustrative example: it is inefficient as the file grows as it has to read and write the entire file every single time.
Note that this will create a file which contains an array of objects, which is how you make lists of objects in JSON. So your final output will look like this:
[
{"name":"name1","phone":"8989898989","adress":"random1"},
{"name":"name1","phone":"767656568","adress":"randomdata1"},
{"name":"name1","phone":"767656568","adress":"randomdata1"}
]
Seems the library u are using can't do that thing. In both methods I find this:
var str = JSON.stringify(obj, options.replacer, spaces) + '\n'
//not sure if fs.writeFileSync returns anything, but just in case
return fs.writeFileSync(file, str, options)
where it writes into file the string you have just passed into the function, so it doesn't evaluate what it is already written into the file. So it will write one json every time you call the function. It won't continue to add elements to the existing json. You should do a custom function to do it.
You could do this:
retrive what it's already in the file
parse into json
append the json object you want to add
stringify the result and save it into the file replacing what was writing first.
edit:
sources:
writeFile /
writeFileSync
I'm successfully using the following extend-script (with json2.js) to read a local JSON file, and change a text layer in my project. How could I modify this script so that, when ran, it continuously 'watches' for new JSON files that are added to the directory, and runs the rest of the script?
#include "json2.js" // jshint ignore:line
var script_file = File($.fileName); // get the location of the script file
var script_file_path = script_file.path; // get the path
var file_to_read = File(script_file_path + "/unique-job-id.json");
var my_JSON_object = null; // create an empty variable
var content; // this will hold the String content from the file
if(file_to_read !== false){// if it is really there
file_to_read.open('r'); // open it
content = file_to_read.read(); // read it
my_JSON_object = JSON.parse(content);// now evaluate the string from the file
//alert(my_JSON_object.arr[1]); // if it all went fine we have now a JSON Object instead of a string call length
var theComposition = app.project.item(1);
var theTextLayer = theComposition.layers[1];
theTextLayer.property("Source Text").setValue(my_JSON_object.arr[2]);
file_to_read.close(); // always close files after reading
}else{
alert("Error reading JSON"); // if something went wrong
}
Look at the Object Model:
Application scheduleTask() method
app.scheduleTask(stringToE xecute, delay, repeat)
Description:
Schedules the specified JavaScript for delayed execution.
So app.scheduleTask(string,delay,true) is exactly what you are looking for.Like this:
app.schduleTask('taskToWatchFile()',1000,true);
function taskToWatchFile(){
/*
*Add your code here
*/
}
I have files such as this that have translation keys and values:
locale-en.json
{
"CHANGE_PASSWORD": "Change Password",
"CONFIRM_PASSWORD": "Confirm Password",
"NEW_PASSWORD": "New Password"
}
locale-jp.json
{
"CHANGE_PASSWORD": "パスワードを変更します",
"CONFIRM_PASSWORD": "パスワードを認証します",
"NEW_PASSWORD": "新しいパスワード"
}
When I add a new translation key to the JSON file containing the English translations for example, I must remember to add that key and the associated translation to all the other JSON files. All the JSON files are also edited separately. The process is laborious and error prone.
Has anyone found a way to reduce the errors and to automate the process.
Ideally I would like to be able to run a script from Windows PowerShell that would change the files to this if an additional key was added to locale-en.json :
locale-en.json
{
"CHANGE_PASSWORD": "Change Password",
"CONFIRM_PASSWORD": "Confirm Password",
"NEW_PASSWORD": "New Password",
"NEW_KEY": "New Key"
}
locale-jp.json
{
"CHANGE_PASSWORD": "パスワードを変更します",
"CONFIRM_PASSWORD": "パスワードを認証します",
"NEW_PASSWORD": "新しいパスワード",
>>>"NEW_KEY": "New Key"
}
You could write something like this in powershell:
$masterFile = "locale-en.json"
function Get-LocaleMap($file){
$map = #{}
$localeJson = ConvertFrom-Json (gc $file -Raw)
$localeJson | gm -MemberType NoteProperty | % {
$map.Add($_.Name, ($localeJson | select -ExpandProperty $_.Name))
}
return $map
}
$masterLocale = Get-LocaleMap $masterFile
ls | ? { $_.Name -like "locale-*.json" -and $_.Name -ne $masterFile } | % {
$locale = Get-LocaleMap $_.FullName
$masterLocale.GetEnumerator() | % {
if(!$locale.ContainsKey($_.Key)){
$locale.Add($_.Key, $_.Value)
}
}
ConvertTo-Json $locale | Out-File -FilePath $_.FullName -Force -Encoding utf8
}
It created a dictionary from your English json file. Then it looks up all other locale files and checks them for keys which are present in the English file but missing from them. Then it adds the missing keys and values and saves the locale files in Unicode.
Let me show you how you can do the same with old school Windows Scripting since you seem to prefer JavaScript:
var masterFile = "locale-en.json"
var fso = new ActiveXObject("Scripting.FileSystemObject");
var scriptPath = fso.GetParentFolderName(WScript.ScriptFullName);
var charSet = 'utf-8';
var f = fso.GetFolder(scriptPath);
var fc = new Enumerator(f.files);
function getLocaleMap(fileName){
var path = scriptPath + '\\' + fileName;
var stream = new ActiveXObject("ADODB.Stream"); // you cannot use fso for utf-8
try{
stream.CharSet = charSet;
stream.Open();
stream.LoadFromFile(path);
var text = stream.ReadText();
var json = {};
eval('json = ' + text); // JSON.parse is not available in all versions
return json;
}
finally{
stream.Close();
}
}
function saveAsUtf8(fileName, text){
var path = scriptPath + '\\' + fileName;
var stream = new ActiveXObject("ADODB.Stream");
try{
stream.CharSet = charSet;
stream.Open();
stream.Position = 0;
stream.WriteText(text);
stream.SaveToFile(path, 2); // overwrite
}
finally{
stream.Close();
}
}
var locales = [];
var masterMap = getLocaleMap(masterFile);
for (; !fc.atEnd(); fc.moveNext())
{
var file = fc.item();
var extension = file.Name.split('.').pop();
if(extension != "json" || file.Name == masterFile){
continue;
}
var map = getLocaleMap(file.Name);
var newLocaleText = '{\r\n';
var i = 0;
for(var name in masterMap){
var value = '';
if(map[name]){
value = map[name];
}
else{
value = masterMap[name];
}
if(i > 0){
newLocaleText += ",\r\n";
}
newLocaleText += "\t'" + name + "': '" + value + "'";
i++;
}
newLocaleText += '\r\n}'
saveAsUtf8(file.Name, newLocaleText);
}
You can run the javascript from command line like this:
Cscript.exe "C:\yourscript.js"
I hope it helps.
Is there a way I can automate the creation of .json files used for language translations?
YES, executing automatic tasks is exactly what automation tools like Grunt and Gulp where designed to do.
As you said, doing things manually is laborious and error prone, so Grunt/Gulp are the way to go.
With a simple Grunt/Gulp config, all the relevant .json files can be watched simultaneously: any key added to any of them will be instantly detected, and order the execution of the custom script of your choice.
HOW GRUNT/GULP CAN DO IT:
Grunt/Gulp will constantly watch all the relevant JSON files;
When a change is detected in a watched file, a custom script is run;
The custom script will read the changed file and retrieve the new key(s) and value(s);
The custom script will then be write to all the other relevant JSON files.
CONFIGURING GRUNT
To detect file changes automatically and execute myCustomScript, just use grunt-contrib-watch like so:
watch: {
scripts: {
files: ['**/*.locale.json'],
tasks: ['myCustomScript'],
},
}
CUSTOM SCRIPT TO ADD THE NEW KEY(S) TO THE RELEVANT .JSON FILES:
grunt.event.on('watch', function(action, filepath) {
// filepath is the path to the file where change is detected
grunt.config.set('filepath', grunt.config.escape(filepath));
});
var myCustomScript=function(changedFile,keyFile){
var project = grunt.file.readJSON(changedFile);
//will store the file where changes were detected as a json object
var keys=grunt.file.readJSON(keyFile);
//will store keyFile as a json object
//walk changedFile keys, and check is keys are in keyFile
for (var key in project) {
if (project.hasOwnProperty(key)) {
if(!keys.hasOwnProperty(key)){
//a new key was detected
newKeyArray.push(key);
}
}
}
//should update all the other relevant JSON files with `grunt.file.write`, and add all the keys in newKeyArray:
var filesToChangeArray=grunt.file.match('**/*.locale.json');
//returns an array that contains all filepaths where change is desired
filesToChangeArray.forEach(function(path){
//walk newKeyArray to set addedContent string
newKeyArray.forEach(function(key){
addedContent+='"'+key+'":"to be set",';
//this will write all the new keys, with a value of "to be set", to the addedContent string
}
grunt.file.write(path,addedContent);
});
}
Ideally I would like to be able to run a script from Windows PowerShell
Even though Grunt/Gulp are often used to execute custom files written in javaScript/nodejs, they are well able to order the execution of scripts written in other languages.
To execute a PowerShell script, you could use a Grunt plugin called grunt-shell, like so:
grunt.initConfig({
shell: {
ps: {
options: {
stdout: true
},
command: 'powershell myScript.ps1'
}
}
});
as detailed in this SO post.
So if PowerShell is your thing, you could have the best of both worlds:
Easy detection with Grunt/Gulp watch;
PowerShell script execution when change is detected.
However, you might as easily use Grunt/Gulp only for this: as Grunt/Gulp is already taking care of the detection in the background, all you need to do is have it run a custom script that reads your new keys (grunt.file.readJSON) and copies them (grunt.file.write) to the relevant files.
Automated the process using a javascript solution with nodejs via command line.
$ node localeUpdater.js
This will watch your default locale (locale-en.json) with any revisions made and update your whole locale file list as necessary.
create the necessary locale file list if not present then initialized it with default locale data
add new keys based on default locale
remove missing keys based on default locale
localeUpdater.js
var fs = require("fs");
var localeFileDefault = "locale-en.json";
var localeFileList = ["locale-jp.json", "locale-ph.json"];
fs.watchFile(localeFileDefault, function() {
var localeDefault = readFile(localeFileDefault);
var localeCurrent = null;
var fileNameCurrent = null;
for (var i in localeFileList) {
fileNameCurrent = localeFileList[i];
console.log("Adding new keys from default locale to file " + fileNameCurrent);
localeCurrent = readFile(fileNameCurrent);
for (var key in localeDefault) {
if (!localeCurrent[key]) {
console.log(key + " key added.");
localeCurrent[key] = localeDefault[key];
}
}
console.log("Removing keys not on default locale to file " + fileNameCurrent);
for (var key in localeCurrent) {
if (!localeDefault[key]) {
console.log(key + " key removed.");
delete localeCurrent[key];
}
}
writeFile(fileNameCurrent, JSON.stringify(localeCurrent));
console.log("File " + fileNameCurrent + " updated.");
}
});
function readFile(fileName) {
var result = null;
if (fs.existsSync(fileName)) {
result = fs.readFileSync(fileName, "utf8");
result = result ? JSON.parse(result) : {};
} else {
writeFile(fileName, "{}");
result = {};
}
return result;
}
function writeFile(fileName, content) {
fs.writeFileSync(fileName, content, "utf8");
}
There are multiple safeguards you should put in place.
First off your translation function should have some safeguards. Something like:
function gettext(text) {
if (manifest[text]) {
return text;
}
return text;
}
I'm not sure how you register new strings, but we regex our code base for things like gettext('...') and then we compile a list of translations that way. A couple times a day we push that to a 3rd party translation company, which notices new strings. They populate new things and we pull content back. The "pull" involves a compilation to the different language files. The translation file compilation always falls back to english. In other words we download a file from the 3rd party and do something like:
_.map(strings, function(string) {
return localeManifest[locale][text] || localeManifest['en_US'][text];
}
This ensures that even if the manifest for the locale doesn't contain the translation yet we still populate it with the English US version.
I'm trying to Append data to a Log file using Node.js and that is working fine but it is not going to the next line. \n doesn't seem to be working in my function below. Any suggestions?
function processInput ( text )
{
fs.open('H://log.txt', 'a', 666, function( e, id ) {
fs.write( id, text + "\n", null, 'utf8', function(){
fs.close(id, function(){
console.log('file is updated');
});
});
});
}
It looks like you're running this on Windows (given your H://log.txt file path).
Try using \r\n instead of just \n.
Honestly, \n is fine; you're probably viewing the log file in notepad or something else that doesn't render non-Windows newlines. Try opening it in a different viewer/editor (e.g. Wordpad).
Use the os.EOL constant instead.
var os = require("os");
function processInput ( text )
{
fs.open('H://log.txt', 'a', 666, function( e, id ) {
fs.write( id, text + os.EOL, null, 'utf8', function(){
fs.close(id, function(){
console.log('file is updated');
});
});
});
}
use \r\n combination to append a new line in node js
var stream = fs.createWriteStream("udp-stream.log", {'flags': 'a'});
stream.once('open', function(fd) {
stream.write(msg+"\r\n");
});
Alternatively, you can use fs.appendFile method
let content = 'some text';
content += "\n";
fs.appendFile("helloworld.txt", content, (err) => {
return console.log(err);
});
Try:
var fs =require('fs');
const details=require('./common');
var info=JSON.stringify(details);
const data=fs.writeFileSync('./tmp/hello/f1.txt',`\n${info}`,{'flag':'a'},function(err,data){
if(err) return console.error("error",error);
console.log(data);
});
//steps to exceute
1.Install all the required modules(ie fs is required here).
2.Here (.common) files has json object which i was importing from another file.
3.then import the file and store in details variable.
4.While performing operations json data has to be converted into string format (so JSON.stringify).
5.WriteFileSync (its an synchronous function)
6.once function execution is completed response is returned.
7.store response in data variable and print in console.log