Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Commit

Permalink
Support for reading byte ranges from files using fs.createReadStream.
Browse files Browse the repository at this point in the history
  • Loading branch information
cskr authored and ry committed Jul 21, 2010
1 parent 56f200a commit f5f7cb9
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 1 deletion.
8 changes: 8 additions & 0 deletions doc/api.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -1583,6 +1583,14 @@ Returns a new ReadStream object (See `Readable Stream`).
, 'bufferSize': 4 * 1024
}

`options` can include `start` and `end` values to read a range of bytes from
the file instead of the entire file. Both `start` and `end` are inclusive and
start at 0. When used, both the limits must be specified always.

An example to read the last 10 bytes of a file which is 100 bytes long:

fs.createReadStream('sample.txt', {start: 90, end: 99});


## fs.WriteStream

Expand Down
25 changes: 24 additions & 1 deletion lib/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,16 @@ var ReadStream = fs.ReadStream = function(path, options) {
this[key] = options[key];
}

if(this.start || this.end) {
if(this.start === undefined || this.end === undefined) {
self.emit('error', new Error('Both start and end are needed for range streaming.'));
} else if(this.start > this.end) {
self.emit('error', new Error('start must be <= end'));
} else {
this.firstRead = true;
}
}

if (this.fd !== null) {
return;
}
Expand Down Expand Up @@ -653,13 +663,22 @@ ReadStream.prototype._read = function () {
allocNewPool();
}

if(this.start && this.firstRead) {
this.pos = this.start;
this.firstRead = false;
}

// Grab another reference to the pool in the case that while we're in the
// thread pool another read() finishes up the pool, and allocates a new
// one.
var thisPool = pool;
var toRead = Math.min(pool.length - pool.used, this.bufferSize);
var start = pool.used;

if(this.pos) {
toRead = Math.min(this.end - this.pos + 1, toRead);
}

function afterRead (err, bytesRead) {
if (err) {
self.emit('error', err);
Expand Down Expand Up @@ -692,7 +711,11 @@ ReadStream.prototype._read = function () {
self._read();
}

fs.read(self.fd, pool, pool.used, toRead, undefined, afterRead);
fs.read(self.fd, pool, pool.used, toRead, this.pos, afterRead);

if(self.pos) {
self.pos += toRead;
}
pool.used += toRead;
};

Expand Down
10 changes: 10 additions & 0 deletions test/simple/test-fs-read-stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Buffer = require('buffer').Buffer;
path = require('path');
fs = require('fs');
fn = path.join(common.fixturesDir, 'elipses.txt');
rangeFile = path.join(common.fixturesDir, 'x.txt');

callbacks = { open: 0, end: 0, close: 0, destroy: 0 };

Expand Down Expand Up @@ -86,3 +87,12 @@ process.addListener('exit', function() {
assert.equal(30000, file.length);
assert.equal(10000, file3.length);
});

var file4 = fs.createReadStream(rangeFile, {start: 1, end: 2});
var contentRead = '';
file4.addListener('data', function(data) {
contentRead += data.toString('utf-8');
});
file4.addListener('end', function(data) {
assert.equal(contentRead, 'yz');
});

0 comments on commit f5f7cb9

Please sign in to comment.