Faster fs.readFile and fs.readFileSync
This commit is contained in:
parent
ee6c11876a
commit
1a2255ab44
137
lib/fs.js
137
lib/fs.js
@ -103,93 +103,88 @@ fs.readFile = function(path, encoding_) {
|
|||||||
var encoding = typeof(encoding_) === 'string' ? encoding_ : null;
|
var encoding = typeof(encoding_) === 'string' ? encoding_ : null;
|
||||||
var callback = arguments[arguments.length - 1];
|
var callback = arguments[arguments.length - 1];
|
||||||
if (typeof(callback) !== 'function') callback = noop;
|
if (typeof(callback) !== 'function') callback = noop;
|
||||||
var readStream = fs.createReadStream(path);
|
|
||||||
var buffers = [];
|
|
||||||
var nread = 0;
|
|
||||||
var error;
|
|
||||||
|
|
||||||
readStream.on('data', function(chunk) {
|
// first, stat the file, so we know the size.
|
||||||
buffers.push(chunk);
|
var size;
|
||||||
nread += chunk.length;
|
var buffer;
|
||||||
});
|
var pos = 0;
|
||||||
|
var fd;
|
||||||
|
|
||||||
readStream.on('error', function(er) {
|
fs.open(path, constants.O_RDONLY, 438 /*=0666*/, function(er, fd_) {
|
||||||
error = er;
|
if (er) return callback(er);
|
||||||
readStream.destroy();
|
fd = fd_;
|
||||||
if (!readStream.fd) {
|
|
||||||
readStream.emit('close');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
readStream.on('close', function() {
|
fs.fstat(fd, function(er, st) {
|
||||||
if (error) {
|
if (er) return callback(er);
|
||||||
return callback(error);
|
size = st.size;
|
||||||
}
|
if (size === 0) {
|
||||||
|
buffer = new Buffer(0);
|
||||||
// copy all the buffers into one
|
return afterRead(null, 0);
|
||||||
var buffer;
|
|
||||||
switch (buffers.length) {
|
|
||||||
case 0: buffer = new Buffer(0); break;
|
|
||||||
case 1: buffer = buffers[0]; break;
|
|
||||||
default: // concat together
|
|
||||||
buffer = new Buffer(nread);
|
|
||||||
var n = 0;
|
|
||||||
buffers.forEach(function(b) {
|
|
||||||
var l = b.length;
|
|
||||||
b.copy(buffer, n, 0, l);
|
|
||||||
n += l;
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (encoding) {
|
|
||||||
try {
|
|
||||||
buffer = buffer.toString(encoding);
|
|
||||||
} catch (er) {
|
|
||||||
return callback(er);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
callback(null, buffer);
|
buffer = new Buffer(size);
|
||||||
|
read();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function read() {
|
||||||
|
fs.read(fd, buffer, pos, size - pos, pos, afterRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
function afterRead(er, bytesRead) {
|
||||||
|
if (er) {
|
||||||
|
return fs.close(fd, function(er2) {
|
||||||
|
return callback(er);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += bytesRead;
|
||||||
|
if (pos === size) close();
|
||||||
|
else read();
|
||||||
|
}
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
fs.close(fd, function(er) {
|
||||||
|
if (encoding) buffer = buffer.toString(encoding);
|
||||||
|
return callback(er, buffer);
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fs.readFileSync = function(path, encoding) {
|
fs.readFileSync = function(path, encoding) {
|
||||||
var fd = fs.openSync(path, constants.O_RDONLY, 438 /*=0666*/);
|
var fd = fs.openSync(path, constants.O_RDONLY, 438 /*=0666*/);
|
||||||
var buffer = new Buffer(4048);
|
|
||||||
var buffers = [];
|
|
||||||
var nread = 0;
|
|
||||||
var lastRead = 0;
|
|
||||||
|
|
||||||
|
var size;
|
||||||
|
var threw = true;
|
||||||
try {
|
try {
|
||||||
do {
|
size = fs.fstatSync(fd).size;
|
||||||
if (lastRead) {
|
threw = false;
|
||||||
buffer._bytesRead = lastRead;
|
|
||||||
nread += lastRead;
|
|
||||||
buffers.push(buffer);
|
|
||||||
}
|
|
||||||
var buffer = new Buffer(4048);
|
|
||||||
lastRead = fs.readSync(fd, buffer, 0, buffer.length, null);
|
|
||||||
} while (lastRead > 0);
|
|
||||||
} finally {
|
} finally {
|
||||||
fs.closeSync(fd);
|
if (threw) fs.closeSync(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffers.length > 1) {
|
if (size === 0) {
|
||||||
var offset = 0;
|
fs.closeSync(fd);
|
||||||
var i;
|
return encoding ? '' : new Buffer(0);
|
||||||
buffer = new Buffer(nread);
|
|
||||||
buffers.forEach(function(i) {
|
|
||||||
if (!i._bytesRead) return;
|
|
||||||
i.copy(buffer, offset, 0, i._bytesRead);
|
|
||||||
offset += i._bytesRead;
|
|
||||||
});
|
|
||||||
} else if (buffers.length) {
|
|
||||||
// buffers has exactly 1 (possibly zero length) buffer, so this should
|
|
||||||
// be a shortcut
|
|
||||||
buffer = buffers[0].slice(0, buffers[0]._bytesRead);
|
|
||||||
} else {
|
|
||||||
buffer = new Buffer(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var buffer = new Buffer(size);
|
||||||
|
var pos = 0;
|
||||||
|
|
||||||
|
while (pos < size) {
|
||||||
|
var threw = true;
|
||||||
|
try {
|
||||||
|
var bytesRead = fs.readSync(fd, buffer, pos, size - pos, pos);
|
||||||
|
threw = false;
|
||||||
|
} finally {
|
||||||
|
if (threw) fs.closeSync(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += bytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.closeSync(fd);
|
||||||
|
|
||||||
if (encoding) buffer = buffer.toString(encoding);
|
if (encoding) buffer = buffer.toString(encoding);
|
||||||
return buffer;
|
return buffer;
|
||||||
};
|
};
|
||||||
|
@ -38,6 +38,10 @@ fs.writeSync = function() {
|
|||||||
throw new Error('BAM');
|
throw new Error('BAM');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fs.fstatSync = function() {
|
||||||
|
throw new Error('BAM');
|
||||||
|
};
|
||||||
|
|
||||||
ensureThrows(function() {
|
ensureThrows(function() {
|
||||||
fs.readFileSync('dummy');
|
fs.readFileSync('dummy');
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user