NodeJS:读取非常大的文件(+ 1GB)的最后X个字节的最有效方法是什么?

时间:2018-02-21 22:41:24

标签: node.js

我想使用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();

3 个答案:

答案 0 :(得分:5)

您基本上想要寻找到文件中的某个位置。有办法做到这一点。请参考这个问题和答案:

seek() equivalent in javascript/node.js?

基本上,确定起始位置(使用其元数据中的文件长度和您感兴趣的字节数),并使用以下方法之一来读取 - 作为流或通过缓冲区 - 您和#的部分39;对...感兴趣。

使用fs.read

  

fs.read(fd, buffer, offset, length, position, callback)

     

position是一个参数,指定从文件中开始读取的位置。

使用fs.createReadStream

或者,如果您要使用createReadStream功能,请指定startend选项:https://nodejs.org/api/fs.html#fs_fs_createreadstream_path_options

  

fs.createReadStream(path[, options])

     

options可以包含startend值,以从文件而不是整个文件中读取字节范围。

答案 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
}