51

What is the best way to read part of a binary file in Node.js?

I am looking to either access specific bytes in the "header" (less than the first 100 bytes) or read the file byte by byte.

3 Answers 3

74

Here is an example of fs.read()-ing the first 100 bytes from a file descriptor returned by fs.open():

var fs = require('fs');

fs.open('file.txt', 'r', function(status, fd) {
    if (status) {
        console.log(status.message);
        return;
    }
    var buffer = Buffer.alloc(100);
    fs.read(fd, buffer, 0, 100, 0, function(err, num) {
        console.log(buffer.toString('utf8', 0, num));
    });
});
Sign up to request clarification or add additional context in comments.

4 Comments

Its utf8 and not utf-8 nodejs.org/api/…
What if I just have byte Buffer?
Pls change status to error to be compat with doc
Searched for hours to find an example like this. Thank you! I posted a question about the same and then made a synchronous version of this thanks to you. stackoverflow.com/questions/74270008/…
3

Using @samplebias answer myself, I've discovered that the code could be much simpler + using proper async functionality instead.

const { open } = require('fs/promises');

const path = 'some/dir/your-file.txt' // change this to your local file's location
const start = 0 // place the reading cursor in this position
const size = 100 // following the example from the original answer. chnage this to suit your needs

const handler = await open(path, 'r')
const { buffer, bytesRead } = await handler.read(Buffer.alloc(size), 0, size, start)

const value = buffer.toString('utf-8', 0, bytesRead)

console.log(value)

Comments

2

This is another option

const fs = require('fs');

const fileName = 'something.bin'

/*
Requirements ex:
Content in 512 bytes chunks. 
Send the 512 bytes packet as a 1024 char string, where each byte is sent as a 
2 hex digits. 
An "addr" field starts from 0 and tracks the offset of the first byte of the 
packet. 
*/
function chunk(s, maxBytes) {
  //! https://nodejs.org/api/buffer.html#buffer_buf_slice_start_end
  /*
    buf.slice([start[, end]])
    start <integer> Where the new Buffer will start. Default: 0.
    end <integer> Where the new Buffer will end (not inclusive). Default: buf.length.
    Returns: <Buffer>
  */

  let buf = Buffer.from(s);  
  const result = [];
  let readBuffer = true
  let startChunkByte = 0
  let endChunkByte = maxBytes
  while(readBuffer) {
    // First round
    startChunkByte === 0 ? endChunkByte = startChunkByte + maxBytes : ""

    //Handle last chunk
    endChunkByte >= buf.length ? readBuffer = false : ""

    // addr: the position of the first bytes.  raw: the chunk of x bytes
    result.push({"addr":startChunkByte,"raw":buf.slice(startChunkByte, endChunkByte).toString('hex')});

    startChunkByte = endChunkByte
    endChunkByte = startChunkByte + maxBytes
  }
  return result;
}

fs.readFile(fileName, (err, data) => {
  if (err) throw err;
  // Let's choose 512 bytes chunks
  const arrBinChunk =  chunk(data, 512)
  arrBinChunk.forEach(element => console.log(element))

  //Tests - should be able to see 1024, 1024, as per riquerements
  arrBinChunk.forEach(element => console.log(element.raw.length))
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.