Node.JSバージョン0.6.3の出力と、Windows XPコンソールで子プロセスエンコーディングを操作しているときに2つのエラーが見つかりました

Node.JS公式ブログ(昨日(11月25日) 、ノードの新しいバージョンが番号0.6.3で発表されました。 変更はそれほど重要ではありません:多数のエラーと欠陥が修正されました。

私はこれを面白くない誕生日プレゼントだと思いました(偶然、11月25日に33歳になりました)。 ただし、同じ日に、「 node.jsから呼び出されたWindowsコマンドの出力を受け入れる方法は?」という質問をします 「私はWindows XPで一連の実験を開始しました。その結果、Windowsでエンコードを操作しているときに2つのノードエラーが発見されました。

まず、 require( 'child_process')。Exec(...)メソッドを使用してコマンドが呼び出されると、NodeはUTF-8でエンコードされた出力を期待しますが、Russified Windowsシステムのコマンド( dirなど )はCP866でエンコードされたテキストを出力します。

第二に、子コンソールプロセスがコンソールエンコーディングを変更した場合、親ノードプロセスのコンソールエンコーディング(特に、 console.logメソッドを使用した出力)にも影響します-それらは同じコンソールまたは何かを持っていることがわかります同じ精神。

そして今、いくつかの詳細。

私が見つけた2つのバグのうち最初のバグは、最も単純なスクリプトを実行して、子プロセスを呼び出し、その出力をリテラル形式でファイルに書き込む場合、遭遇するのは難しくありません。
var fs = require('fs'); // file system require('child_process').exec('dir', function(err, outstr){ fs.createWriteStream('testfile.txt', { flags: 'w', encoding: 'binary' }).write(outstr); }); 

ファイル内のロシア文字の代わりにナンセンスがあります。

sdevalexが正しく示唆したように 、この問題の回避策があります。Windowsの 「chcp」コマンドを使用して、呼び出されたプロセスのエンコーディングを変更するだけです。 これを念頭に置いてコンパイルされたスクリプトは、目的のタイプのコマンド出力をテキストファイルに表示します。
 var forker = require('child_process'); var fs = require('fs'); // file system forker.exec('chcp 65001 | dir', function(err, outstr){ fs.createWriteStream('testfile.txt', { flags: 'w', encoding: 'binary' }).write(outstr); }); 

ただし、この回避策では、ファイルだけでなくコンソールにも結果を出力する場合、2番目のエラーが発生する可能性があります。このスクリプトを記述するのに十分です。
 var clog = console.log; clog('\nRunning under Node.js version ' + process.versions.node + ' on ' + process.arch + '-type processor, ' + process.platform + ' platform.'); var forker = require('child_process'); var fs = require('fs'); // file system forker.exec('chcp 65001 | dir', function(err, outstr){ fs.createWriteStream('testfile.txt', { flags: 'w', encoding: 'binary' }).write(outstr); clog('\n' + outstr); }); 

つまずくことができます。 そして、奇妙なことに、つまずかないことができます。 コンソールでラスターフォントを使用するかベクターフォントを使用するか(Windows XPではLucida Consoleフォントで再生されます)、つまり、使い慣れたコンソールプロパティダイアログボックスの2番目のタブの中央の設定に依存します。

[コンソールプロパティウィンドウ]

私が覚えている限りでは、Windows XPはデフォルトでコンソールでビットマップフォントを使用します(間違っている場合は修正してください)。 したがって、自分でこの設定を変更していない場合、上記のスクリプトは必要なテキストをファイル(「testfile.txt」)に出力し、魅力のないものがコンソールに出力されます。

[コンソールのスクリーンショット]

これはすべて、ラスターコンソールで「chcp」コマンドがコマンドによって表示されるテキストのエンコードのみを変更するためです。 ビットマップフォントはそれに適応できないため、コンソールでの「chcp」コマンドの出力でさえ見苦しくなります。

[chcpスクリーンショット]

コンソールがベクターフォント(Lucida Console)でテキストを表示するように構成されている場合、 「chcp」コマンドを使用してコンソールで事前に設定したものは何でも、スクリプト出力が正しいように見えるため、この問題に気付かないでしょう

[ベクターコンソールのスクリーンショット]

この段階で、髪の毛は頭に逆らって立ち、ゆっくりと動きます。 開発者(ベクターコンソールを使用している場合)が、自分と他の多くのユーザー(ラスターコンソール)で正常に機能する10行のコードでスクリプトを作成できる、異常に潜んでいる問題があることが明らかだからです。予防的に。

しかし、この問題は何ですか?

JavaScriptでは文字列がユニコードであり、WindowsコンソールではCP866でエンコードされているため、おそらくNodeはWindowsコンソールへの出力に対応していませんか? そして、ここにありますが、これはそうではありません-コンソールへの簡単なテスト出力で簡単に証明できます:

[テストのスクリーンショット]

おそらく、出力文字がCP866エンコーディングを超えると、ノードはゴミに切り替わりますか? いいえ。これを確認するには、 \ u2248 \ u0422 \ u0435 \ u0441 \ u0442の行を印刷するだけで十分です。 文字\ u2248 」自体は疑問符に置き換えられますが、行の残りの部分は影響を受けません。

別の推測が当てはまることがわかります。ラスターコンソールのこのゴミは、コードページの変更に関するメッセージではなく、コマンド「chcp 65001」によって表示されるゴミと同じ性質のものです。 さらに彼が呼ばれるのはまさにそれです 。 このコマンドを子プロセスで指定し、dirコマンドで表示されるテキストのエンコードを変更することを意図しました-ただし、chcpコマンドは親コンソールに影響しました!

これを完全に実証するには、簡単なテストで十分です。

[別のテストのスクリーンショット]

ご覧のとおり、子プロセスからの「chcp 65001」は親プロセスのコンソールウィンドウで動作します(コマンド「chcp 866」が発行され、デフォルトのCP866コードページが返されるまで動作します)。

この新しいエラーを理解することで、以前に見つかったエラーを回避するより良い方法を発見できます。 「dir」コマンドの前に「chcp 65001」を呼び出すと、「chcp 866」を再度呼び出して、 「dir」コマンドによって発行されたテキストを表示する前にコンソールを元の状態に戻す必要があります

 var clog = console.log; clog('\nRunning under Node.js version ' + process.versions.node + ' on ' + process.arch + '-type processor, ' + process.platform + ' platform.'); var forker = require('child_process'); var fs = require('fs'); // file system forker.exec('chcp 65001 | dir', function(err, outstr){ fs.createWriteStream('testfile.txt', { flags: 'w', encoding: 'binary' }).write(outstr); forker.exec('chcp 866', function(){ clog('\n' + outstr); }); }); 

このスクリプトはすでに、テストファイルだけでなくコンソールにも完璧なテキストをシームレスに出力できます。

[別のテストのスクリーンショット]

この回避策は、その完璧さにもかかわらず 、克服できないアーキテクチャ上の欠陥があります。もちろん、2つの.exec()呼び出しは非同期であるため、それらの間でコンソールはしばらくの間異常モードのままになります。

両方のエラーはGitHubを介してNode開発者に報告されました: donnerjack13589は昨日問題2190を作成し、今日は問題2196を作成しました。

Source: https://habr.com/ru/post/J133426/


All Articles