web-dev-qa-db-ja.com

node.jsでのバイナリデータの読み取り

Node.jsのバイナリデータの読み取りに問題があります。これが私がすることです:

$ cat test.js 
var fs = require('fs'),
    binary = fs.readFileSync('./binary', 'binary').toString('binary');
process.stdout.write(binary.substring(0, 48));
$ xxd binary
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
00000010: 0300 3e00 0100 0000 0008 0000 0000 0000  ..>.............
00000020: 4000 0000 0000 0000 10a0 0000 0000 0000  @...............
$ node test.js | xxd
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
00000010: 0300 3e00 0100 0000 0008 0000 0000 0000  ..>.............
00000020: 4000 0000 0000 0000 10c2 a000 0000 0000  @...............
00000030: 00                                       .
$

ノードで読み取るときに、インデックス0x29に0xc2バイトが挿入されることに注意してください。何故ですか? readFileSynctoStringの両方にバイナリエンコーディングを指定しました。私もアスキーを試しましたが、違う間違った結果になります。

6
Robert Larsen

'binary'エンコーディングは'latin1'のエイリアスです。これは、文字以外のデータを読み取る場合には明らかに望ましくありません。

生データが必要な場合は、 エンコードを指定しないでください (またはnull)*を指定します。文字列の代わりに Buffer を取得します。これは、toStringを使用するのではなく、直接使用することになります。

*(一部のAPI [fs.watch]なども'buffer'を受け入れますが、 エンコーディングのリスト には含まれておらず、readFileSyncはそうではありません。 Patrick リストリンクを提供してくれてありがとう。])

9
T.J. Crowder

さらに情報を追加するために、これが発生する理由は、文字列をstdout.write()に渡しているためです。これは、書き込まれる前に暗黙的にBufferに変換され、ノードでそれを行うときに発生します。 js REPLバイナリファイルの0x28の位置にこの特定のサブストリングがある場合、説明した動作が得られます。

_> new Buffer('\u0010\u00a0')
<Buffer 10 c2 a0>
_

@ T.J.Crowderが正しく提案したように、スクリプトを修正する方法は次のとおりです。

_var fs = require('fs'),
    binary = fs.readFileSync('./binary');
process.stdout.write(binary.slice(0, 48));
_

また、Buffer#slice()の代わりに String#substring() を使用します。

6
Patrick Roberts