UNPKG

@versatiles/container

Version:
65 lines (64 loc) 3.83 kB
import fs from 'node:fs'; /** * Creates a file reader function for reading chunks of data from a file. This reader abstracts * the file reading process and provides a simple async interface to read data from the specified file. * The reader keeps the file open, hence it should be used in contexts where the file is not * expected to be modified by other processes. It's important to manage the lifecycle of the file * descriptor properly and ensure it's closed when no longer needed. * * @param {string} filename - The name of the file to read from. This file must exist and be readable, * otherwise the function will throw an error when trying to open it. * @returns {Reader} A reader function that when called, returns a promise. This promise resolves with a * Buffer containing the read bytes from the file. The function reads `length` bytes of data * from the file starting at `position`. If an error occurs during the read operation, * the promise is rejected with the error. If `position` is beyond the end of the file, * the promise resolves to an empty buffer. If the read operation attempts to read beyond * the end of the file, the promise resolves with a buffer that contains only the bytes * that could be read. */ export default function getFileReader(filename) { const fd = fs.openSync(filename, 'r'); const { size } = fs.statSync(filename); /** * Reads a chunk of data from the file at the specified position and length. * It creates a buffer of the specified `length`, seeks to the `position` in the file, * and reads `length` bytes into the buffer. This function is intended to be used with files * that are not being concurrently modified, as it relies on consistent file state to * function correctly. * * @param {number} position - The starting position in the file to read from. If this position * is beyond the end of the file, the function will resolve to an * empty buffer. * @param {number} length - The number of bytes to read from the file starting at `position`. * If `length` extends beyond the end of the file, the returned buffer * will only include the bytes that could be read up to the end of the file. * @returns {Promise<Buffer>} A promise that resolves with the buffer containing the read bytes. If * an error occurs during the read, such as if the position is invalid or * the file descriptor becomes invalid due to the file being closed, the * promise will be rejected with an error. */ return async function read(position, length) { if (position < 0) { throw new RangeError(`Invalid read position: ${position}. The read position must be a non-negative integer.`); } if (length < 0) { throw new RangeError(`Invalid read length: ${length}. The read length must be a non-negative integer.`); } if (position + length > size) { throw new RangeError(`Read range out of bounds: The requested range ends at position ${position + length}, which exceeds the file's limit of ${size} bytes.`); } return new Promise((resolve, reject) => { fs.read(fd, { buffer: Buffer.alloc(length), position, length, }, (err, _, buf) => { if (err) { reject(err); return; } resolve(buf); }); }); }; }