Read file line by line without buffering the whole file in memory.
npm install n-readlines






> 📖 Read files line-by-line, synchronously. Zero dependencies.
Reading a file line by line may seem trivial, but in Node.js there's no straightforward way to do it. Many libraries use Transform Streams which feels like overkill for such a simple task. This library uses only Node's built-in fs module to provide a clean, synchronous API.
- 🚀 Simple API — just next() to get the next line
- 📦 Zero dependencies — only uses Node.js built-ins
- 🔄 Synchronous — no callbacks or promises to manage
- 💾 Memory efficient — reads in chunks, doesn't load entire file
- 🔧 Configurable — custom chunk sizes
- 📘 TypeScript support — includes type definitions
- 🪟 Cross-platform — handles LF, CRLF, and CR line endings automatically
- 📥 Stdin support — read from stdin by passing fd 0
- 🥟 Bun compatible — works with Bun runtime
- 🦕 Deno compatible — works with Deno runtime
``bash`
npm install n-readlines
Requirements: Node.js >= 18.x, Bun, or Deno
`javascript
const LineByLine = require('n-readlines');
const liner = new LineByLine('./textfile.txt');
let line;
while (line = liner.next()) {
console.log(line.toString());
}
`
`typescript
import LineByLine = require('n-readlines');
const liner = new LineByLine('./textfile.txt');
let line: Buffer | null;
while (line = liner.next()) {
console.log(line.toString());
}
`
`javascript`
new LineByLine(filename, [options])
new LineByLine(fd, [options])
| Parameter | Type | Description |
|-----------|------|-------------|
| filename | string | Path to the file to read |fd
| | number | File descriptor (0 for stdin, or from fs.openSync) |options.readChunk
| | number | Bytes to read at once. Default: 1024 |
#### .next() → Buffer | null
Returns the next line as a Buffer (without the newline character), or null when end of file is reached.
`javascript`
const line = liner.next();
if (line !== null) {
console.log(line.toString()); // Convert Buffer to string
}
#### .reset()
Resets the reader to the beginning of the file.
`javascript`
liner.next(); // Read first line
liner.next(); // Read second line
liner.reset(); // Go back to start
liner.next(); // First line again
> Note: reset() does not work with stdin.
#### .close()
Manually closes the file. Subsequent next() calls will return null.
`javascript`
liner.next();
liner.close(); // Done reading early
liner.next(); // Returns null
> Note: When reading from stdin, close() does not close the stdin stream.
#### .isLast() → boolean
Returns true if the last line has been read and there are no more lines available.
`javascript
const liner = new LineByLine('./file.txt');
while (true) {
const line = liner.next();
if (line === null) break;
console.log(line.toString());
if (liner.isLast()) {
console.log('This was the last line!');
}
}
`
`javascript
const LineByLine = require('n-readlines');
const liner = new LineByLine('./data.txt');
let line;
let lineNumber = 1;
while (line = liner.next()) {
console.log(Line ${lineNumber}: ${line.toString('utf8')});
lineNumber++;
}
console.log('Finished reading file');
`
`javascript
const LineByLine = require('n-readlines');
const liner = new LineByLine(0); // fd 0 = stdin
let line;
while (line = liner.next()) {
console.log(line.toString());
}
`
Usage:
`bash`
echo -e "line1\nline2\nline3" | node script.js
cat file.txt | node script.js
`javascript`
const liner = new LineByLine('./large-file.txt', {
readChunk: 4096 // Read 4KB at a time
});
`javascript
const LineByLine = require('n-readlines');
const liner = new LineByLine('./data.jsonl');
let line;
while (line = liner.next()) {
const record = JSON.parse(line.toString());
console.log(record);
}
`
`javascript
const liner = new LineByLine('./log.txt');
let line;
while (line = liner.next()) {
const text = line.toString();
if (text.includes('ERROR')) {
console.log('Found error:', text);
liner.close(); // Stop reading
break;
}
}
`
- Lines are returned as Buffer objects — call .toString() to convert to stringnull
- The newline character is not included in the returned line
- Files without a trailing newline are handled correctly
- Empty lines are preserved and returned as empty buffers
- Returns (not false) when end of file is reached
The library automatically handles all common line ending formats:
| Format | Characters | Platform |
|--------|------------|----------|
| LF | \n | Unix, Linux, macOS |\r\n
| CRLF | | Windows |\r` | Classic Mac OS |
| CR |
Files with mixed line endings are also supported — each line is detected individually.
MIT © Yoan Arnaudov