我想使用node.js有效地读取非常大的文件的最后X个字节。这样做最有效的方法是什么?
据我所知,这样做的唯一方法是创建一个读取流并循环,直到命中字节索引。
示例:
// lets assume I want the last 10 bytes;
// I would open a stream and loop until I reach the end of the file
// Once I did I would go to the last 10 bytes I kept in memory
let f = fs.createReadStream('file.xpto'); //which is a 1gb file
let data = [];
f.on('data', function(data){
for (d of data){
data.push(d)
data = data.slice(1,11); //keep only 10 elements
}
})
f.on('end', function(){
// check data
console.log('Last test bytes is', data)
})
f.resume();
答案 0 :(得分:5)
您基本上想要寻找到文件中的某个位置。有办法做到这一点。请参考这个问题和答案:
seek() equivalent in javascript/node.js?
基本上,确定起始位置(使用其元数据中的文件长度和您感兴趣的字节数),并使用以下方法之一来读取 - 作为流或通过缓冲区 - 您和#的部分39;对...感兴趣。
fs.read
fs.read(fd, buffer, offset, length, position, callback)
position
是一个参数,指定从文件中开始读取的位置。
fs.createReadStream
或者,如果您要使用createReadStream
功能,请指定start
和end
选项:https://nodejs.org/api/fs.html#fs_fs_createreadstream_path_options
fs.createReadStream(path[, options])
options
可以包含start
和end
值,以从文件而不是整个文件中读取字节范围。
答案 1 :(得分:2)
以下是基于Arash Motamedi答案的示例代码。 这将让您在几毫秒内读取一个非常大的文件的最后10个字节。
let fs = require('fs');
const _path = 'my-very-large-file.xpto';
const stats = fs.statSync(_path);
let size = stats.size;
let sizeStart = size-10;
let sizeEnd = size;
let options = {
start: sizeStart,
end: sizeEnd
}
let stream = fs.createReadStream(_path, options)
stream.on('data',(data)=>{
console.log({data});
})
stream.resume()
答案 2 :(得分:0)
对于 promised 版本的读取解决方案:
import FS from 'fs/promises';
async function getLastXBytesBuffer() {
const bytesToRead = 1024; // The x bytes you want to read
const handle = await FS.open(path, 'r');
const { size } = await handle.stat(path)
// Calculate the position x bytes from the end
const position = size - bytesToRead;
// Get the resulting buffer
const { buffer } = await handle.read(Buffer.alloc(bytesToRead), 0, bytesToRead, position);
// Dont forget to close filehandle
await handle.close()
return buffer
}