Search code examples
javascriptnode.jsbinaryendiannesstyped-arrays

Node - How to write a typed array to a binary file with a specified endianness


I have a typed array and I want to write it to a binary file. I need it to be in big-endian byte order but I might not (usually won't be) on a big-endian machine. How do I get from my typed array to the binary file?


Solution

  • As you may know, the way to enforce endianness in javascript is with the DataView view. Once you've created a DataView view of your buffer, you can set and get the data from it in either big-endian or little-endian byte order.

    Here's an example of turning a typed array (which may be in little- or big-endian byte order) into a Uint8Array (equivalent to Node's 'file' Buffer) in big-endian byte order. Notice that since the dataView is a just a view of the underlying buffer, the original array arr is now byte-swapped and we will write it to the file.

    arr = new Float32Array([42]) // one value
    dataView = new DataView(arr.buffer)
    dataView.setFloat32(0, arr[0], false /* big-endian */)
    buf = new Uint8Array(arr.buffer)
    

    Now you can pass that Array into a node file-writing method since Uint8Array is compatible with Node's Buffer object. For example, if you already had opened a file and had the fd for it, then you could do something like this:

    fs.writeSync(fd, buf)
    

    For the sake of completeness, here's example code which handles the loop you would actually use with Float32-type data:

    arr = new Float32Array([...]) // some initial data
    ...
    dataView = new DataView(arr.buffer)
    byteNum = 0;
    for (let i = 0; i < arr.length; i++) {
      dataView.setFloat32(byteNum, arr[i]);
      byteNum += Float32Array.BYTES_PER_ELEMENT;
    }
    
    buf = new Uint8Array(arr.buffer)
    fs.writeSync(fd, buf)
    

    Note in the above that I didn't pass false to setFloat32 because that's the default.


    (For more details on the writing part of this see: Writing files in Node.js)