简体   繁体   中英

Map binary buffer to Int16Array or Int32Array

Say I read a binary file into a Buffer object as in the following lines

const fs = require('fs');
var file_content = fs.readFileSync(fileNamePath);

Now let's say the file_content is equal to:

<Buffer 50 4b 03 04 01 2b b4 52 >

In decimal, these byte values would be:

<Buffer 80 75 3 4 1 43 180 82 >

These are 8 bytes. I need to cast them into an int array, either Int16Array or Int32Array.

in the case of Int16Array. I'm expecting the following value:

Int16Array(4) [20555, 772, 299, 46162]

and in the case of Int32Array I'm expecting:

Int32Array(2) [1347093252, 012bb452]

As in the above examples, I'm expecting that when casting to Int16Array, the 8 bytes will be cast into only 4 Ints because each takes two bytes. And in the case of Int32Array, I'm expecting only 2 because each is supposed to take 4 bytes.

Yet, when I do the following:

var int16a = Int16Array.from(file_content);
var int32a = Int32Array.from(file_content);
console.log(int16a, int32a);

The output is:

Int16Array(8) [ 80, 75, 3,  4, 1, 43, 180, 82 ] 
Int32Array(8) [ 80, 75, 3,  4, 1, 43, 180, 82 ]

Such that in both cases it casts only one byte to each Int.

Don't use from , which iterates the bytes of the node buffer and puts them in the typed array as integers.

Instead, construct a typed array as a view on the node Buffer 's underlying .buffer :

const fs = require('fs');
const file_content = fs.readFileSync(fileNamePath);

const int16a = new Int16Array(file_content.buffer, file_content.byteOffset, file_content.length/2);
const int32a = new Int32Array(file_content.buffer, file_content.byteOffset, file_content.length/4);
console.log(int16a, int32a);

Unless you must have the storage array to have 16bit types, I prefer using the Buffer methods such as readInt16LE() or readInt32BE() to produce number or bigint primitives. It also gives you greater control over byte order, Int16Array etc uses the platform endianness. You can also read integers up to 6 bytes (48-bits) into a number primitive.

Using your example buffer for 16-bit integers:

var shorts = [];
for (let offset = 0; offset < file_content.length; offset += 2)
    shorts.push(file_content.readInt16LE(offset));

For 32-bits:

var ints = [];
for (let offset = 0; offset < file_content.length; offset += 4)
    ints.push(file_content.readInt32LE(offset));

Example 6 bytes: var six = file_content.readIntLE(0, 6);

Note the endianness and the sign. See all the functions here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM