Skip to content

Commit

Permalink
v0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Gabriel Llamas committed Apr 25, 2012
1 parent 7eb380c commit 4e45a02
Show file tree
Hide file tree
Showing 12 changed files with 358 additions and 9 deletions.
6 changes: 5 additions & 1 deletion README.md
Expand Up @@ -7,7 +7,11 @@ Node BufferedReader

[Availability](#availability) | [Compatibility](#compatibility) | [Documentation](#documentation)

Version: 0.0.6
Version: 0.1.0

When you need to read a file you typically read a chunk of bytes called "buffer" to avoid multiple calls to the underliying I/O layer, so instead of reading directly from the disk, you read from the previous filled buffer. Doing that you win performance.

This library allows you to read files using internal buffers, so you don't have to worry about them. In addition, you can read a text file line by line.

<a name="availability"></a>
#### Availability [](#start) ####
Expand Down
2 changes: 1 addition & 1 deletion build/buffered-reader.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions build/package.json
@@ -1,8 +1,9 @@
{
"name": "buffered-reader",
"version": "0.0.6",
"version": "0.1.0",
"description": "Fully configurable buffered reader.",
"keywords": ["buffer", "reader", "line", "read line", "read file", "read text file", "file"],
"keywords": ["buffer", "reader", "line", "read line", "file", "read file", "read text file",
"read binary file", "binary"],
"author": {
"name": "Gabriel Llamas"
},
Expand Down
29 changes: 29 additions & 0 deletions examples/chunkBytes.js
@@ -0,0 +1,29 @@
var BufferedReader = require ("../build/buffered-reader");

console.log ("File size: 16");

new BufferedReader ("file").readBytes (10, function (error, bytes, bytesRead){
if (error) console.log (error);

console.log (bytes);
console.log ("Bytes read: " + bytesRead);

this.readBytes (8, function (error, bytes, bytesRead){
if (error) console.log (error);

console.log (bytes);
console.log ("Bytes read: " + bytesRead);

this.readBytes (4, function (error, bytes, bytesRead){
if (error) console.log (error);

//No more bytes, reached the end of the file
console.log (bytes);
console.log ("Bytes read: " + bytesRead);

this.close (function (error){
if (error) console.log (error);
});
});
});
});
Binary file added examples/file
Binary file not shown.
162 changes: 159 additions & 3 deletions src/buffered-reader.js
Expand Up @@ -4,17 +4,20 @@
*
* @author Gabriel Llamas
* @created 10/04/2012
* @modified 21/04/2012
* @version 0.0.6
* @modified 25/04/2012
* @version 0.1.0
*/
"use strict";

var EVENTS = require ("events");
var FS = require ("fs");
var PATH = require ("path");

var BUFFER_SIZE = 16384;

var INVALID_BUFFER_SIZE = new Error ("The buffer size must be greater than 0.");
var INVALID_BYTES_RANGE_ERROR = new Error ("The number of bytes must be greater than 0.");
var NO_FILE_ERROR = new Error ("The source is not a file.");

var BufferedReader = function (fileName, bufferSize, encoding){
EVENTS.EventEmitter.call (this);

Expand All @@ -27,12 +30,22 @@ var BufferedReader = function (fileName, bufferSize, encoding){
bufferSize = BUFFER_SIZE;
}

if (bufferSize < 1) throw INVALID_BUFFER_SIZE;

this._settings = {
encoding: encoding,
bufferSize: bufferSize
};

this._fileName = fileName;
this._fd = null;
this._buffer = null;
this._fileOffset = 0;
this._bufferOffset = 0;
this._eof = false;
this._noMoreBuffers = false;
this._fileSize = null;
this._dataOffset = 0;
};

BufferedReader.prototype = Object.create (EVENTS.EventEmitter.prototype);
Expand Down Expand Up @@ -104,4 +117,147 @@ BufferedReader.prototype.read = function (){
});
};

BufferedReader.prototype._open = function (cb){
if (this._fd) return cb (null, this._fd);

var me = this;
FS.stat (this._fileName, function (error, stats){
if (error) return cb (error, null);
if (stats.isFile ()){
FS.open (me._fileName, "r", function (error, fd){
if (error) return cb (error, null);

me._fileSize = stats.size;
me._fd = fd;
me._buffer = new Buffer (me._settings.bufferSize);
me._read (function (error){
if (error){
return cb (error, null);
}else{
cb (null, me._fd);
}
});
});
}else{
cb (NO_FILE_ERROR, null);
}
});
};

BufferedReader.prototype._read = function (cb){
var me = this;
var size = this._settings.bufferSize;
FS.read (this._fd, this._buffer, 0, size, this._fileOffset, function (error, bytesRead){
if (error) return cb (error);

me._bufferValidSize = bytesRead;
me._fileOffset += bytesRead;
if (me._fileOffset === me._fileSize){
me._noMoreBuffers = true;
}
if (bytesRead < size){
me._buffer = me._buffer.slice (0, bytesRead);
}
cb ();
});
};

BufferedReader.prototype.close = function (cb){
if (cb) cb = cb.bind (this);
if (!this._fd){
if (cb) cb (null);
return;
}

var me = this;
FS.close (this._fd, function (error){
me._fd = null;
me._buffer = null;
if (cb) cb.call (me, error);
});
};

BufferedReader.prototype.readBytes = function (bytes, cb){
cb = cb.bind (this);
if (bytes < 1) return cb (INVALID_BYTES_RANGE_ERROR, null, -1);
if (this._eof) return cb (null, null, 0);

var fill = function (){
var endData = bytes - me._dataOffset;
var endBuffer = me._buffer.length - me._bufferOffset;
var end = endData > endBuffer ? endBuffer : endData;

me._buffer.copy (data, me._dataOffset, me._bufferOffset, me._bufferOffset + end);
me._bufferOffset += end;
if (me._bufferOffset === me._buffer.length) me._bufferOffset = 0;
me._dataOffset += end;

if (me._dataOffset === bytes){
me._dataOffset = 0;
me._eof = me._noMoreBuffers;
cb (null, data, bytes);
}else{
if (me._noMoreBuffers){
me._eof = true;
end = me._dataOffset;
me._dataOffset = 0;
cb (null, data.slice (0, end), end);
}else{
me._read (function (error){
if (error) return cb (error, null, -1);

fill ();
});
}
}
};

var me = this;
var data = new Buffer (bytes);

this._open (function (error, fd){
if (error) return cb (error, null, -1);

var len = me._buffer.length;

if (bytes < len){
var end = me._bufferOffset + bytes;

if (end <= len){
me._buffer.copy (data, 0, me._bufferOffset, end);
me._bufferOffset = end;
cb (null, data, bytes);
}else{
var last = len - me._bufferOffset;
if (last !== 0){
me._buffer.copy (data, 0, me._bufferOffset, me._bufferOffset + last);
}
if (me._noMoreBuffers){
me._eof = true;
return cb (null, data.slice (0, last), last);
}

me._read (function (error){
if (error) return cb (error, null);

len = me._buffer.length;
var remaining = bytes - last;
if (len <= remaining){
me._eof = true;
me._buffer.copy (data, last, 0, len);
var lastChunk = last + len;
cb (null, data.slice (0, lastChunk), lastChunk);
}else{
me._bufferOffset = remaining;
me._buffer.copy (data, last, 0, me._bufferOffset);
cb (null, data, bytes);
}
});
}
}else{
fill ();
}
});
};

module.exports = BufferedReader;
5 changes: 3 additions & 2 deletions src/package.json
@@ -1,8 +1,9 @@
{
"name": "buffered-reader",
"version": "0.0.6",
"version": "0.1.0",
"description": "Fully configurable buffered reader.",
"keywords": ["buffer", "reader", "line", "read line", "read file", "read text file", "file"],
"keywords": ["buffer", "reader", "line", "read line", "file", "read file", "read text file",
"read binary file", "binary"],
"author": {
"name": "Gabriel Llamas"
},
Expand Down
Binary file added test/tests/file
Binary file not shown.
59 changes: 59 additions & 0 deletions test/tests/test1.js
@@ -0,0 +1,59 @@
var BufferedReader = require ("../../build/buffered-reader");

new BufferedReader ("file", 5).readBytes (2, function (error, bytes, bytesRead){
if (error) console.log (error);
console.log (bytes);
console.log ("bytes read: " + bytesRead);

this.readBytes (2, function (error, bytes, bytesRead){
if (error) console.log (error);
console.log (bytes);
console.log ("bytes read: " + bytesRead);

this.readBytes (2, function (error, bytes, bytesRead){
if (error) console.log (error);
console.log (bytes);
console.log ("bytes read: " + bytesRead);

this.readBytes (2, function (error, bytes, bytesRead){
if (error) console.log (error);
console.log (bytes);
console.log ("bytes read: " + bytesRead);

this.readBytes (2, function (error, bytes, bytesRead){
if (error) console.log (error);
console.log (bytes);
console.log ("bytes read: " + bytesRead);

this.readBytes (2, function (error, bytes, bytesRead){
if (error) console.log (error);
console.log (bytes);
console.log ("bytes read: " + bytesRead);

this.readBytes (2, function (error, bytes, bytesRead){
if (error) console.log (error);
console.log (bytes);
console.log ("bytes read: " + bytesRead);

this.readBytes (2, function (error, bytes, bytesRead){
if (error) console.log (error);
console.log (bytes);
console.log ("bytes read: " + bytesRead);

this.readBytes (2, function (error, bytes, bytesRead){
if (error) console.log (error);
console.log (bytes);
console.log ("bytes read: " + bytesRead);

this.close (function (error){
if (error) console.log (error);
});
});
});
});
});
});
});
});
});
});
41 changes: 41 additions & 0 deletions test/tests/test2.js
@@ -0,0 +1,41 @@
var BufferedReader = require ("../../build/buffered-reader");

new BufferedReader ("file", 5).readBytes (4, function (error, bytes, bytesRead){
if (error) console.log (error);
console.log (bytes);
console.log ("bytes read: " + bytesRead);

this.readBytes (3, function (error, bytes, bytesRead){
if (error) console.log (error);
console.log (bytes);
console.log ("bytes read: " + bytesRead);

this.readBytes (2, function (error, bytes, bytesRead){
if (error) console.log (error);
console.log (bytes);
console.log ("bytes read: " + bytesRead);

this.readBytes (1, function (error, bytes, bytesRead){
if (error) console.log (error);
console.log (bytes);
console.log ("bytes read: " + bytesRead);

this.readBytes (4, function (error, bytes, bytesRead){
if (error) console.log (error);
console.log (bytes);
console.log ("bytes read: " + bytesRead);

this.readBytes (3, function (error, bytes, bytesRead){
if (error) console.log (error);
console.log (bytes);
console.log ("bytes read: " + bytesRead);

this.close (function (error){
if (error) console.log (error);
});
});
});
});
});
});
});

0 comments on commit 4e45a02

Please sign in to comment.