Node.js - How to write variable file names - javascript

I'd like to run an SVG-PDF-converter, which processes all files in a folder and creates the PDF output files with the corresponding file names:
var fs = require('fs'),
PDFDocument = require('pdfkit'),
SVGtoPDF = require('svg-to-pdfkit'),
glob = require("glob"),
inputFiles = glob.sync('./input/**/*.svg');
for (let i = 0; i < inputFiles.length; i++) {
var doc = new PDFDocument(),
stream = fs.createWriteStream('./output/' + inputFiles[i] + '.pdf'),
svg = fs.readFileSync(inputFiles[i], 'utf-8');
SVGtoPDF(doc, svg, 0, 0);
doc.pipe(stream);
doc.end();
};
Obviously it doesn't work that way...
How can I use variable file names in createWriteStream?

Short answer: Use backquote like this
fs.createWriteStream(`./somefolder/${fileName}.pdf`)

var fileName = String(inputFiles[i]),
outputString = fileName.replace("input", "output"),
outputStringComplete = outputString.replace("svg", "pdf"),
stream = fs.createWriteStream(outputStringComplete);

You can do something like this to actually fetch the filename using regex. You will get the filenames then you can use this filename to create new file.
const fileDetails = glob.sync('yourpathtodir');
const regex = new RegExp(/[^\\\/]+(?=\.[\w]+$)|[^\\\/]+$/);
const fileNames = [];
fileDetails.forEach(el => fileNames.push(regex.exec(el)[0]));
console.log(fileNames);
for (let i = 0; i < fileNames.length; i++) {
var doc = new PDFDocument(),
stream = fs.createWriteStream(`./output/${fileNames[i]}.pdf`),
svg = fs.readFileSync(`${fileNames[i]}.svg`, 'utf-8'); // you might need to provide full name for file
SVGtoPDF(doc, svg, 0, 0);
doc.pipe(stream);
doc.end();
};

Related

Count the number of items in Array in nodejs

I have big file almost 2GB and text also includes so many countries, sometimes twise and more. I should create script what will write to stdout all countries from the file and also will show how many times the country name was used. for example if there is germany five times in file code Should show us: Germany: 5 (something like that)
const fs = require("fs");
readline = require("readline");
stream = require("stream");
const filename = process.argv[2];
const instream = fs.createReadStream(filename);
const outstream = new stream();
outstream.readable = true;
outstream.writable = true;
const rl = readline.createInterface({
input: instream,
output: outstream,
terminal: false,
});
rl.on("line", function (line) {
const [country] = line.split(",", 1);
Str = country;
var obj = new Object();
for (var i = 0; i < Str.length; i++) {
if (obj[Str] != null) {
obj[Str] += 1;
} else {
obj[Str] = 1;
}
}
console.log(obj);
});
I wrote this but it shows the number of letters in word.
Thank you (link for download file is in comments)
Here is a part of text:
united
states,2001,dinner-and-a-murder-mystery-games,retail,linkedin.com/company/dinner-and-a-murder-mystery-games,"",dinner
and a murder mystery games,tennessee,1-10,dinnerandamurder.com
netherlands,2013,jennifer-campbell,management
consulting,linkedin.com/company/jennifer-campbell,houten,jennifer
campbell,utrecht,1-10,jennifercampbell.com united
states,"",imtec-corp,marketing and
advertising,linkedin.com/company/imtec-corp,ardmore,imtec corp
italy,1977,bo.ma-s.r.l.,research,linkedin.com/company/bo.ma-s.r.l.
Your problem is probably, that you have a variable "country" that contains the country as string and then you store it to Str and do:
"for (var i = 0; i < Str.length; i++) {
this loops over every char in the stream.
Also you need to define the "obj" outside of the callback otherwise it gets recreated for every line.
Just try:
var obj = {};
rl.on("line", function (line) {
const [country] = line.split(",", 1);
if (obj[country]) {
obj[country]++;
} else {
obj[country] = 1;
}
console.log(obj);
});

How to Directly Instantiate WebAssembly Module in JavaScript

The examples I've seen show essentially this:
fetch('simple.wasm').then(response =>
response.arrayBuffer()
).then(bytes =>
WebAssembly.instantiate(bytes, {})
).then(result =>
result.instance.exports...
)
But I would like to do it without making that extra HTTP request. Wondering if the only way is this (or some variation of it, which would be helpful to know):
var binary = '...mywasmbinary...'
var buffer = new ArrayBuffer(binary.length)
var view = new DataView(buffer)
for (var i = 0, n = binary.length; i < n; i++) {
var x = binary[i]
view.setInt8(i * 8, x)
}
Wondering if I have to worry about endianess or anything like that.
Or perhaps doing something with URL and blobs might be better, I'm not sure.
Yes, you are correct, in order to inline wasm modules and avoid the HTTP request, you'll have to perform some sort of encoding. I'd recommend using Base64 encoded strings as they are the most compact form.
You can encode as follows:
const readFileSync = require('fs').readFileSync;
const wasmCode = readFileSync(id);
const encoded = Buffer.from(wasmCode, 'binary').toString('base64');
You can then load the module as follows:
var encoded = "... contents of encoded from above ...";
function asciiToBinary(str) {
if (typeof atob === 'function') {
// this works in the browser
return atob(str)
} else {
// this works in node
return new Buffer(str, 'base64').toString('binary');
}
}
function decode(encoded) {
var binaryString = asciiToBinary(encoded);
var bytes = new Uint8Array(binaryString.length);
for (var i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes.buffer;
}
var module = WebAssembly.instantiate(decode(encoded), {});

Recursive function Javascript concat array result - ImageJ

I try to make a javascript code for ImageJ, wich have to goal to allow me to select a directory, and return me all jpg and jpeg file in the directory and sub-directory.
I have do this code, it's work well for direct children, he call well getJpeg on subdirectories (I have verify it with some IJ.log), but the jpeg Array is not concat with result of recursives call
Have you an idea?
importClass(Packages.ij.IJ);
importClass(Packages.ij.plugin.frame.RoiManager);
importClass(Packages.ij.gui.GenericDialog);
importClass(Packages.ij.io.OpenDialog);
importClass(Packages.java.io.File);
var dirstr = IJ.getDirectory("Choose the stacks folder");
var jpeg = getJpeg(dirstr);
for (var i = 0; i < jpeg.length; i++) {
IJ.log(jpeg[i]);
}
function getJpeg(dirst) {
var dir = new java.io.File(dirst);
var names = dir.listFiles();
var jpeg = new Array();
for (var i = 0 ; i < names.length; i++) {
if(names[i].isDirectory()){
jpeg.concat(getJpeg(names[i].getPath()));
continue;
}
var namest = names[i].getName();
if (namest.match(/.*\.jpg|jpeg/)) {
var path = names[i].getPath();
jpeg.push(path);
}
}
return jpeg;
}
Thank you :)
The problem come from a missread from concat documentation ( w3schools.com/jsreF/jsref_concat_array.asp ). Have to put
jpeg = jpeg.concat(getJpeg(names[i].getPath()));

Convert a byteArray into an IntegerArray using javascript

I receive a bytearray and I want to convert it into a intarray.
Is this possible in NodeJS?
Reason to do that:
A proxy receives values from a serialconnection which is a bytearray and I try to decode that and put it into a more specific JSON object.
var uint8Message = new Uint8Array(8),
output = [];
uint8Message[0] = 40;
uint8Message[1] = 40;
uint8Message[2] = 40;
uint8Message[3] = 40;
uint8Message[4] = 40;
uint8Message[5] = 40;
uint8Message[6] = 40;
uint8Message[7] = 40;
var counter = 0;
var intermediate = [];
for (var i = 0; i< uint8Message.byteLength; i++) {
if (counter < 4) {
intermediate.push(uint8Message[i]);
}
counter++;
if (counter === 3 ){
output.push(new Uint16Array(intermediate));
counter = 0;
intermediate = [];
}
}
console.log(output);
I am sending a intArray which is converted to byteArray from arduino to a NodeJS serialport handler. I want to get 8 integer values in array:
Status and value for four engines.
So in the end I want to have this:
[1,89,2,49,1,28,3,89]
Which is not complete correct with the example. But the example above is for testing.
Still not sure I understand your question correctly but if you want to convert Uint8Array to say Uint32Array you could do
const uint8Array = new Uint8Array(8).fill(40)
console.log(new Uint32Array(uint8Array.buffer))
If you need plain old js array you could do
const uint8Array = new Uint8Array(8).fill(40)
const intArray = Array.from(new Uint32Array(uint8Array.buffer))
console.log(Array.isArray(intArray))
Also you might want to take a look at what is called DataView that allows low level access to buffers' contents.

How to convert a CSV file into a JSON script using Node.js?

test.csv file has:
"Id","UserName","Age"
"01","Sam Smith","33"
"02","Fred Frankly","44"
"03","Zachary Zupers","55"
acpected output: as Json File
[{"id":01,"User Name": " Sam Smith", "Age":"33"},
{"id":03,"User Name": " Fred Frankly", "Age":"44"}
{"id":03,"User Name": "Aachary Zupers", "Age":"55"}
]
I tried to solve like this using node.js
var fs = require("fs");
var data = fs.readFileSync('test.csv');
var stringData=data.toString();
console.log(stringData);
var arrayOne= stringData.split('\r\n');
var header=arrayOne[0].split(',');
var noOfRow=arrayOne.length;
var noOfCol=header.length;
var jArray=[];
var i=0,j=0;
for (i = 1; i < noOfRow-1; i++) {
for (j = 0; j< noOfCol; j++) {
var myNewLine=arrayOne[i].split(',');
jArray.push( '{'+header[j]+':'+myNewLine[j]+'}');
};
};
console.log( jArray);
this is the output I got when I run the above code:
output Image
In the above code I have just tried to show in json script. But If you can do that. Please provide the code to convert the displayed output into a .json file.
Please help me I shall be thankful to you.
As ShanShan mentioned you can leverage an external library for this in a real project, but I've made some modifications to your code that should do what you want in case you're doing this as a learning experience.
I've tried to keep the code roughly the same. There are two major changes. First, rather than construct a string with the content I'm creating an object that stores the data that you're interested in for each row. Because this object is on a per-row level, this is in the outer loop that handles rows. Second, I'm stripping out the first and last character of the header and value text (the quotes). Because you're interepreting the CSV as a string and splitting based on that, it still contains the quotes. In the real world you might want to extract this with a regex or a replace function, but I tried to keep it simple so it uses substring instead.
The code below:
var fs = require("fs");
var data = fs.readFileSync('test.csv');
var stringData=data.toString();
console.log(stringData);
var arrayOne= stringData.split('\r\n');
var header=arrayOne[0].split(',');
var noOfRow=arrayOne.length;
var noOfCol=header.length;
var jArray=[];
var i=0,j=0;
for (i = 1; i < noOfRow-1; i++) {
var obj = {};
var myNewLine=arrayOne[i].split(',');
for (j = 0; j< noOfCol; j++) {
var headerText = header[j].substring(1,header[j].length-1);
var valueText = myNewLine[j].substring(1,myNewLine[j].length-1);
obj[headerText] = valueText;
};
jArray.push(obj);
};
console.log( jArray);
try this:
...
var jArray=[];
var i=0,j=0;
for (i = 1; i < noOfRow-1; i++) {
for (j = 0; j< noOfCol; j++) {
var myNewLine=arrayOne[i].split(',');
jArray.push(JSON.parse( '{'+header[j]+':'+myNewLine[j]+'}'));
};
};
fs.writeFile('test.json', JSON.stringify(jArray), function (err) {
if (err) return console.log(err);
console.log('ok');
});
console.log( jArray);
This should work
var fs = require('fs');
var data = fs.readFileSync('test.csv');
var parsed = data.toString().split('\r\n').splice(1).map(function(d) {
var splitted = d.split(',');
return {
id: parseInt(JSON.parse(splitted[0])),
user_name: JSON.parse(splitted[1]),
age: parseInt(JSON.parse(splitted[2]))
};
});
console.log(parsed);
If you care to not re invent the wheel,
Given a csv such
NAME, AGE
Daffy Duck, 24
Bugs Bunny, 22
you could do like this
var csv = require('csv-parser')
var fs = require('fs')
fs.createReadStream('some-csv-file.csv')
.pipe(csv())
.on('data', function (data) {
console.log('Name: %s Age: %s', data.NAME, data.AGE)
})
see more here

Categories