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を作成しました。



All Articles