Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force UTF-8 in node js with exec process?

Tags:

I know the solution is very simple, but it's an hour I'm banging my head.

In Windows 10, if i launch the command "dir", i got this result:

Il volume nell'unità D non ha etichetta.

in Node js i try to exec the dir command in this way:

var child = exec('dir', {'encoding': 'UTF-8'}, (err, stdout, stderr) => {
  console.log(stdout);
});

and i got this result: Il volume nell'unit� C non ha etichetta.

Ah, damned accented letter!

I tried using UTF-16 and then, convert to string:

var child = exec('dir', {'encoding': 'UTF-16'}, (err, stdout, stderr) => {
  let b: Buffer = stdout;
  let o: string;
  o = stdout.toString('UTF-8');
  console.log(o);
});

I get the same cursed result:

"Il volume nell'unit� C non ha etichetta."

Can you help me to solve this rebus? What am I doing wrong?

It almost seems that the exec command does not accept UTF-8 encoding In fact, if I run this script to force conversion from UTF-8 to string:

var child = exec(j.cmd, {'encoding': 'UTF-8'}, (err, stdout, stderr) => {
  var utf8 = require('utf8');
  var o: string = utf8.decode(stdout)
  console.log(o);
});

i got this error:

..\node_modules\utf8\utf8.js:194 throw Error('Invalid UTF-8 detected');

Any idea?

like image 604
Janka Avatar asked Oct 06 '17 10:10

Janka


1 Answers

When you use dir in the command prompt the renderer knows which character encoding stdout is using, decodes the text bytes and renders the characters with the selected font.

When you exec a command, node does not know which character encoding stdout is using, so you tell it. The problem is you are telling it the wrong thing. To see which character encoding it is, go chcp. But, out-of-the-box, node only supports some of the dozens of characters encodings.

The solution is to tell the command prompt to use one they have in common. Since you are getting paths from the filesystem and the filesystem (NTFS) uses the Unicode character set for paths, UTF-8 is a great choice.

So, this should work:

exec('@chcp 65001 >nul & dir', {encoding: "UTF-8"}, 
    (err, stdout, stderr) => console.log(stdout));

But, the chcp command has a delayed effect and isn't applied to the dir command. Here is one way of working around that:

exec('@chcp 65001 >nul & cmd /d/s/c dir', {encoding: "UTF-8"}, 
    (err, stdout, stderr) => console.log(stdout));

Running a batch file might be a simpler way to get two separate commands to run with sequential effect but that would require setup and clean up.

like image 200
Tom Blodget Avatar answered Sep 25 '22 17:09

Tom Blodget