diff --git a/doc/api.markdown b/doc/api.markdown index 321edf753f..2660f9503c 100644 --- a/doc/api.markdown +++ b/doc/api.markdown @@ -1396,7 +1396,7 @@ is a string--what was read--and `bytesRead` is the number of bytes read. Synchronous version of `fs.read`. Returns an array `[data, bytesRead]`. -### fs.readFile(filename, encoding='utf8', callback) +### fs.readFile(filename, [encoding,] callback) Asynchronously reads the entire contents of a file. Example: @@ -1408,6 +1408,8 @@ Asynchronously reads the entire contents of a file. Example: The callback is passed two arguments `(err, data)`, where `data` is the contents of the file. +If no encoding is specified, then the raw buffer is returned. + ### fs.readFileSync(filename, encoding='utf8') Synchronous version of `fs.readFile`. Returns the contents of the `filename`. diff --git a/lib/fs.js b/lib/fs.js index abb0a5e99c..610d0532f7 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -1,5 +1,6 @@ var sys = require('sys'), - events = require('events'); + events = require('events'), + Buffer = require('buffer').Buffer; var binding = process.binding('fs'); var fs = exports; @@ -38,34 +39,39 @@ fs.Stats.prototype.isSocket = function () { return this._checkModeProperty(process.S_IFSOCK); }; - -function readAll (fd, pos, content, encoding, callback) { - binding.read(fd, 4*1024, pos, encoding, function (err, chunk, bytesRead) { - if (err) { - if (callback) callback(err); - } else if (chunk) { - content += chunk; - pos += bytesRead; - readAll(fd, pos, content, encoding, callback); - } else { - binding.close(fd, function (err) { - if (callback) callback(err, content); - }); - } - }); -} - fs.readFile = function (path, encoding_, callback) { - var encoding = typeof(encoding_) == 'string' ? encoding_ : 'utf8'; + var encoding = typeof(encoding_) == 'string' ? encoding_ : null; var callback_ = arguments[arguments.length - 1]; - var callback = (typeof(callback_) == 'function' ? callback_ : null); - binding.open(path, process.O_RDONLY, 0666, function (err, fd) { - if (err) { - if (callback) callback(err); - } else { - // leave pos null to allow reads on unseekable devices - readAll(fd, null, "", encoding, callback); - } + var callback = (typeof(callback_) == 'function' ? callback_ : noop); + binding.stat(path, function (err, stat) { + if (err) { callback(err); return; } + binding.open(path, process.O_RDONLY, 0666, function (err, fd) { + if (err) { callback(err); return; } + var size = stat.size; + var buffer = new Buffer(size); + var offset = 0; + function doRead() { + // position is offset or null so we can read files on unseekable mediums + binding.read(fd, buffer, offset, size - offset, offset || null, function (err, amount) { + if (err) { callback(err); return; } + if (amount + offset < size) { + offset += amount; + doRead(); + return; + } + if (encoding) { + try { + callback(null, buffer.toString(encoding)); + } catch (err) { + callback(err); + } + } else { + callback(null, buffer); + } + }); + } + doRead(); + }); }); }; diff --git a/lib/module.js b/lib/module.js index 4c40f3754e..ae6c0413b6 100644 --- a/lib/module.js +++ b/lib/module.js @@ -339,7 +339,7 @@ function cat (id, callback) { } }); } else { - requireNative('fs').readFile(id, callback); + requireNative('fs').readFile(id, 'utf8', callback); } } diff --git a/test/simple/test-ini.js b/test/simple/test-ini.js index 489950daff..2d2bb55122 100644 --- a/test/simple/test-ini.js +++ b/test/simple/test-ini.js @@ -8,7 +8,7 @@ debug("load fixtures/fixture.ini"); p = path.join(fixturesDir, "fixture.ini"); -fs.readFile(p,function(err, data) { +fs.readFile(p, 'utf8', function(err, data) { if (err) throw err; assert.equal(typeof parse, 'function');