reading data from multiple files in javascript - javascript

I have a set of template files present in folder say /root/path/templates/ and corresponding input files at path say /root/path/inputs/<template_name>/. Here <template_name> indicates the folder name which holds all the input files for a given template.
Let's say template file contains v
List item
alue as %1 %2 which are like place holders, where we need to replace the %n with the line number from input file line which are present in /root/path/inputs/<template_name>/.
For example:
template file name as `t1.template` and its content are `%1 %2`
Input files are `in1.input` and `in2.input` at path `/root/path/inputs/t1`.
The content for in1.input as:
First
Second
The content for in2.input is
Third
Fourth
My expected output should be like this:
t1/in1.output
First Second
t1/in2.output
Third Fourth
Now the template file can have any characters say:
`This is a template file with %1 %2 fields. Also it has %%1 percenage`
Here the corresponding output should be :
t1/in1.output
This is a template file with First Second fields. Also it has %1 percenage
t1/in2.output
This is a template file with Third Fourth fields. Also it has %1 percenage
means only %1 and %2 placeholders should be replaced. If %%n then while generating result show it as %n, it is not treated as placeholder.
Now I am trying to implement this using JS and Node:
var fs = require('fs');
var arr = fs.readdirSync("/root/path/templates");
var response = "";
for(let i=0; i<arr.length; i++) {
var item = arr[i];
var hastemplate = item.indexOf(".template");
if(hastemplate > -1) {
var tempName = item.substring(0, hastemplate);
var lineReader = require("readline").createInterface({
input: fs.createReadStream("/root/path/inputs/"+tempName)
});
lineReader.on("line", function(line) {
console.log(line + ' ' +tempName);
});
}
}
Input to this program:
/root/path/templates/t1.template
/root/path/inputs/t1/in1.input
/root/path/inputs/t1/in2.input
/root/path/templates/t2.template
When I try to print the file name in lineReader I am getting it as t2.template, i am not able to properly read the data from t1.template and its files in1.input and in2.input.
I also want to know how to read the input files and maintain the order for the output.
So got stuck here with my code incomplete.

As #Felix Kling stated in the comments, it is a scope problem and it is triggered by the fact that lineReader.on("line", ...) is not synchronous.
Here is an example illustrating your bug in a shorter manner:
for (let i = 0; i < 3; i++) {
var temp = i;
setTimeout(() => console.log(i, temp), 1000);
}
Output:
0 2
1 2
2 2
The first time var temp is encountered, the variable temp is created, then every time the loop runs, the original variable is modified. As the loop ends before any of the setTimeout calls, all of them will "know" that temp = 2.
Using let or const would bind the variable to the context of each iteration, a new variable is created each time. I highly suggest using const to leverage some advantages of immutability too, when it is the case.
const fs = require('fs');
const arr = fs.readdirSync("/root/path/templates");
let response = "";
for(let i=0; i<arr.length; i++) {
const item = arr[i];
const hastemplate = item.indexOf(".template");
if(hastemplate > -1) {
const tempName = item.substring(0, hastemplate);
const lineReader = require("readline").createInterface({
input: fs.createReadStream("/root/path/inputs/"+tempName)
});
lineReader.on("line", function(line) {
console.log(line + ' ' +tempName);
});
}
}

Related

How do you put a value in a similar key over and over again in javascript

I want to receive the Excel data and put the value in the Excel column as a loop statement.
I want to put it in with the code below, what should I do?
//read file
const workbook = XLSX.readFile("test.xlsx");
//put value
workbook.Sheets.Sheet1.B2.v = 2000
workbook.Sheets.Sheet1.B3.v = 3000
workbook.Sheets.Sheet1.B4.v = 4000
You can use bracket notations along with a for loop to do this.
With [] notation, you can use a variable to access a property of an object.
Initialize with a suitable value and run up til some limit. Here is sample code:
const workbook = XLSX.readFile("test.xlsx");
let cellsLimit = 100;
for(let i = 1 ; i <= cellsLimit; i++){
let keyName = 'B' + i;
workbook.Sheets.Sheet1[keyName].v = 1000 + (i*1000)
}

Take variable values and put them in another file

I'm coding the game blockly, I have a variable called lineCount which counts the number of line breaks. however this variable is in a file called lib-dialog.js. When I insert the value of this variable with innerHTML I can get the value of lines by creating a div in the soy.js file (File by which I need to treat the result) But I need this value in a variable to put an if(lines == 6) { }
// Add the user's code.
if (BlocklyGames.workspace) {
var linesText = document.getElementById('dialogLinesText');
linesText.textContent = '';
// Line produces warning when compiling Puzzle since there is no JavaScript
// generator. But this function is never called in Puzzle, so no matter.
var code = Blockly.JavaScript.workspaceToCode(BlocklyGames.workspace);
code = BlocklyInterface.stripCode(code);
var noComments = code.replace(/\/\/[^\n]*/g, ''); // Inline comments.
noComments = noComments.replace(/\/\*.*\*\//g, ''); /* Block comments. */
noComments = noComments.replace(/[ \t]+\n/g, '\n'); // Trailing spaces.
noComments = noComments.replace(/\n+/g, '\n'); // Blank lines.
noComments = noComments.trim();
var lineCount = noComments.split('\n').length;
var pre = document.getElementById('containerCode');
pre.textContent = code;
if (typeof prettyPrintOne == 'function') {
code = pre.innerHTML;
code = prettyPrintOne(code, 'js');
pre.innerHTML = code;
}
if (lineCount == 1) {
var text = BlocklyGames.getMsg('Games_linesOfCode1');
} else {
var text = BlocklyGames.getMsg('Games_linesOfCode2')
.replace('%1', String(lineCount));
}
linesText.appendChild(document.createTextNode(text));
document.getElementById("contarBloco").innerHTML = lineCount;
var contandoBloco = lineCount;
}
I need to take the variable lineCount and put its value in another js.but I'm only managing to insert it into a div with innerHTML
it is better you use localstorage . Set the value of localcount in the local storage and get wherever you want
var lineCount = noComments.split('\n').length;
localStorage.setItem("lineCount", lineCount); // in first file
var count = localStorage.getItem("lineCount") // in second file
with this logic you will get the value but it will be string then for that you either use directly string or convert into integer using parseInt method
parseInt(count);
may be it will help . Thanks
I don't know if your Javascript files are modules, if so, you can return a function in your lib-dialog.js page and return it.
Example
lib-dialog.js =
let Dialog = (function() {
function SetLineCountVariable(LocalLineCount){
LineCount = LocalLineCount;
}
return SetLineCountVariable
})();
And in your soy.js file
let Soy = (function() {
Dialog.SetLineCountVariable(6);
})();
And do not forgot to call your JS file in order in your HTML page
Another way, if you only want the variable result in your another JS file, in your lib-dialog.js, show the result of LineCount in html tag and get it in your another JS file with document.getElementById

Check for value within test of TestCafe

I use TestCafe to automate testing a specific function. In this function, the user is only allowed to have 5 entries. On the site is a label that indicates how many entries are left.
When the user already has 5 entries it should delete one in order to test adding a new one.
The html markup of the page is:
<p class="pull-left text-muted">5 / 5 possible entries</p>
Now I want to get exactly this string to make a little if/else with JavaScript to delete an entry when it says 5 / 5 possible entries. So far I have this test-code:
await t
.expect(location.pathname).eql(addresspath);
const extractEntries = Selector("p").withText("possible entries");
console.log('[DEBUG], Entries: ' + extractEntries.toString());
var entries = extractEntries.toString().substring(0, 1);
console.log('[DEBUG], character: ' + entries);
When the test runs, on the output of extractEntries.toString() outputs this:
[DEBUG], Entries: function __$$clientFunction$$() {
var testRun = builder.getBoundTestRun() || _testRunTracker2.default.resolveContextTestRun();
var callsite = (0, _getCallsite.getCallsiteForMethod)(builder.callsiteNames.execution);
var args = [];
// OPTIMIZATION: don't leak `arguments` object.
for (var i = 0; i < arguments.length; i++) {
args.push(arguments[i]);
}return builder._executeCommand(args, testRun, callsite);
}
And the next line:
[DEBUG], character: f
I have tried extractEntries.textContent, extractEntries.innerHTML, extractEntries.innerText but I am not able to get the text 5 / 5 possible entries.
What would be the solution to access the text?
TestCafe Selectors provide asynchronous properties to obtain element state values. To get element text, call the textContent property with the await directive:
const paragraph = Selector("p").withText("possible entries");
const extractEntries = await paragraph.textContent;

Javascript get all files minus certain file extentions

I have a script that returns all the files contained within a folder. However, there are some file types in there that I do not want my script to do anything with. I just want it to literally skip over it as if it wasn't there and only deal with the other file types.
How can I achieve this?
So far this is how I'm getting all the files contained within a folder:
var samplesFolder = Folder(Path)
//Get the files
var fileList = samplesFolder.getFiles()
//Creat Array to hold names
var renderTypes = new Array();
//Parse Initial name to get similar render elements
var beautyRender = fileList[0].name
beautyRender = beautyRender.substr(0, beautyRender.length-4)
//Get the render elements with a similar name
for (var i = 0; i < fileList.length; i++)
{
if(fileList[i].name.substring(0,beautyRender.length) === beautyRender)
{
renderTypes[i] = fileList[i].name
}
}
This is not used for web purposes I should hasten to add.
edit
Above is the complete code I have to get all the image files in a folder and bring them into photoshop once the user has selected the folder they want to use. At the moment it is bringing in every single image in the folder when there is a single type I want it to ignore.
You can iterate over the list and only collect those with extensions you care about. i see photoshop so I'll assume image files only:
var distilledFileList = [];
for (var i = 0; i < fileList.length; i++){
if (/\.(?:jpe?g|png|gif|psd)$/i.test(fileList[i].name)){
distilledFileList.push(fileList[i]);
}
}
Now distilledFileList contains only *.jpg, *.jpeg, *.png, *.gif, and *.psd files.
if you want an easier (more readable) way to check extensions (maybe you're not as fluent as regular expressions):
// fileList = ....
// setup an array of bad extensions here:
var bad = ['txt', 'log', 'db'],
// holds new list of files that are acceptable
distilledFileList = [];
// iterate over entire list
for (var i = 0; i < fileList.length; i++){
// grab the file extenion (if one exists)
var m = fileList[i].name.match(/\.([^\.]+)$/);
// if there is an extenions, make sure it's now in the
// 'bad' list:
if (m && bad.indexOf(m[1].toLowerCase()) != -1){
// it's safe, so add it to the distilled list
distilledFileList.push(fileList[is]);
}
}
Assuming fileList is just an array of strings you could do something along the lines of:
for (var i = 0, len = fileList.length; i < len; i++) {
var filename = fileList[i].name;
if (filename.match(/\.(txt|html|gif)$/i) !== null) { continue; }
// Your logic here
}
Where txt, html and gif are file extensions you want to skip over, you can add more by separating them with |

reading all the submatches in regexp multiple matches

today i'm trying to parse a 'ps aux' output (issued from a node.js server)
so i made an happy regex to parse the values, and i wanted to put all those fancy informations into a simple JSON object :-)
problem is, the regex i've made has 3 match groups, doing multiple matches... and i don't even know if it's possible to have it all the matches returned.
var spawn = require("child_process").spawn;
function exec(http_req, http_resp){
var re_ps = /(?:([\d\.\w\-\?\/\+]+)\s+){8}(?:((?:\d+\:\d+)|(?:\w+\d+))\s+){2}([^\n]+)/g,
result_re_ps,
array_re_ps = [];
//[USER, PID, %CPU, %MEM, VSZ, RSS, TTY, STAT], dates[START, TIME], COMMAND
var ps_process = spawn("ps", ["aux"]);
ps_process.stdout.on("data", function(data){
var split_data = data.toString().split('\n');
for (var i=1; i < 2; i++){
while ((result_re_ps = re_ps.exec(split_data[i])) != null){
console.log("--- while iteration ---");
console.dir(result_re_ps);
//console.dir(result_re_ps);
}
}
//http_resp.write(data);
});
ps_process.on("exit", function (code) {
if (code !== 0) {
console.log("ps_process exited with code " + code);
}
http_resp.end();
});
}
exports.exec = exec;
the "--- while iteration ---" it's just one per each line, instead, it should be multiples!
I will link a fancy screenshot to let you visually understand what kind of data i'm expecting
As you can see the above are 3 groups of data, each one with multiple occurrences
Any help? :p
EDITED TO CLARIFY:
This is the result of a line like:
root 5213 0.0 2.1 8688 2760 ? Ss 11:33 0:01 sshd: root#pts/0
As you can see, the resulting array is 1-dimensional, instead for the results to be contained entirely it HAS to be at least 2-dimensional
UPDATE:
For now i've solved the problem changin my code like this:
var spawn = require("child_process").spawn;
function exec(http_req, http_resp){
var array_re_ps = [];
var re_ps1 = /(?:([\d\.\w\-\?\/\+]+)\s+)/g,
re_ps2 = /(?:((?:\d+\:\d+)|(?:\w+\d+))\s+)/g,
re_ps3 = /([^\n]+)/g;
//[USER, PID, %CPU, %MEM, VSZ, RSS, TTY, STAT], dates[START, TIME], COMMAND
var ps_process = spawn("ps", ["aux"]);
ps_process.stdout.on("data", function(data){
var split_data = data.toString().split('\n');
for (var i=20; i < 21; i++){
array_re_ps[0] = [], array_re_ps[1] = [];
for (var j=0; j<8; j++){
array_re_ps[0].push(re_ps1.exec(split_data[i])[1]);
}
re_ps2.lastIndex = re_ps1.lastIndex;
for (var j=0; j<2; j++){
array_re_ps[1].push(re_ps2.exec(split_data[i])[1])
}
re_ps3.lastIndex = re_ps2.lastIndex;
array_re_ps[2] = re_ps3.exec(split_data[i])[1];
console.dir(array_re_ps);
}
});
ps_process.on("exit", function (code) {
if (code !== 0) {
console.log("ps_process exited with code " + code);
}
http_resp.end();
});
}
exports.exec = exec;
Basically i split my long regexp, in 3 smaller ones, and i do cycle through their results.
If you try the code i formatted the resulting array exactly as i wanted, but i still think that it's a side-solution.
Since Regular Expressions lets you "multiple parse group multiple times", it is possible to have that functionality in javascript?
Take a look at the return values of the exec function.
It returns the index where it first matched, the original string and the capture groups in the elements [0]...[n].
All this is available in your output, you just have to iterate through the single elements of the array.

Categories

Resources