简体   繁体   English

NodeJS 通过 Steam 运行文件

[英]NodeJS Running through file by steams

I'm trying to read through a file using a stream. The file is a custom file format that has some number of sections, each being 66 bytes.我正在尝试使用 stream 读取一个文件。该文件是一种自定义文件格式,具有一定数量的部分,每个部分为 66 字节。 I have to check the value of the the first 32 bytes against a given 32 bytes, and if they match return the remaining 34 bytes.我必须根据给定的 32 个字节检查前 32 个字节的值,如果它们匹配,则返回剩余的 34 个字节。 Currently I'm doing the following目前我正在做以下事情

const fs = require('fs')

/**
 * @param {string} known
 */
function check(known) {
  let stream = fs.createReadStream('path/to/file', {highWaterMark: 66});
  let out = '';
  stream.on('data', (chunk) => {
    let temp = '';
    for (let i = 0; i < 32; i++) {
      temp += String.fromCharCode(chunk.at(i));
    }
    if (temp === known) {
      for (let i = 32; i < 66; i++) {
        out += String.fromCharCode(chunk.at(i));
      }
    }
  });
  return out;
}

However (from checking with console.log ) I know that the function in stream.on is run after check "finishes" so regardless of if the given string is found, the returned value will always be the same.但是(通过检查console.log )我知道 stream.on 中的stream.oncheck “完成”后运行,因此无论是否找到给定的字符串,返回的值始终相同。 How fix?怎么修? Thanks in advance提前致谢

Streams are non-blocking and asynchronous.流是非阻塞和异步的。 They call their event handlers some time in the future, after your check() function has returned.在您的check() function 返回后,他们会在将来某个时间调用他们的事件处理程序。 That is how they work.这就是他们的工作方式。

As such, you cannot directly return your result from the function because the function returns before the result is known.因此,您不能直接从 function 返回结果,因为 function 在结果已知之前返回。 Instead, you have to return the result using an asynchronous mechanism such as an event, a callback or a promise (I would prefer a promise in this case).相反,您必须使用异步机制返回结果,例如事件、回调或 promise(在这种情况下我更喜欢 promise)。 see How to return the response from an asynchronous call for more detail on returning your asynchronously retrieved value.有关返回异步检索值的更多详细信息,请参阅如何从异步调用返回响应

But, using a stream to read a file that is structured in 66 byte chunks is the hard way to write this code because data blocks are going to be randomly sized and are not guaranteed to line up with your 66 byte blocks.但是,使用 stream 读取以 66 字节块结构化的文件是编写此代码的困难方法,因为data块的大小将是随机的,并且不能保证与 66 字节块对齐。 It would be simpler to use const fileHandle = await fs.promises.open(...) and fileHandle.read(...) to read a 66 byte chunk from the beginning of the file, check the 32 bytes you want to check and then communicate back the remaining 34 bytes using a promise.使用const fileHandle = await fs.promises.open(...)fileHandle.read(...)从文件开头读取 66 字节块会更简单,检查要检查的 32 字节然后使用 promise 传回剩余的 34 个字节。

Here's one such way to write it using handle.read() instead:这是一种使用handle.read()来编写它的方法:

const fsp = require('fs').promises;

async function check(known) {
    const kReadLen = 66;
    const kHeaderLen = 32;
    let handle = await fsp.open('path/to/file');
    try {
        let buffer = Buffer.alloc(kReadLen, 0);
        let { bytesRead } = await handle.read(buffer, 0, kReadLen, 0);
        if (bytesRead !== readLen) {
            throw new Error("Insufficient data in the file");
        }
        const headerStr = buffer.toString('utf8', 0, kHeaderLen);
        if (headerStr === known) {
            return buffer.toString('utf8', kHeaderLen, kReadLen);
        } else {
            return "";
        }
    } finally {
        handle.close();
    }
}

Sample Usage:示例用法:

check(testKnown).then(result => {
    console.log(result);
}).catch(err => {
    console.log(err);
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM