从Node fs读取流中每次n行数据。

huangapple go评论61阅读模式
英文:

Read from Node fs read stream n number of lines at a time

问题

我想保持fs读取流开启,并在需要时手动读取n行。我不想使用on()事件处理程序与'data'连接,因为它会使流自动连续读取,直到结束。在手动触发读取下一组行之前,无法确定需要多长时间。

英文:

I want to keep the fs read stream open and read n number of lines at a time whenever I want manually. I don't want to hook up the on() event handler with 'data' as it makes the stream to continuously read automatically until the end. There is no telling how long it would take before it's manually triggered to read the next set of lines are read.

答案1

得分: 1

我已经创建了一个简短的函数,应该可以满足你的需求。

const { createReadStream } = require('fs');
// 将所有内容包装在异步函数中,以便可以使用 await
// 在全局 await 可用时不需要
(async () => {
  // 创建可读流
  const stream = createReadStream('lorem.txt', { encoding: 'utf-8' })

  // 获取 readLine 函数实例
  const { readLine } = await createReader(stream)

  // 读取100行,你可以读取任意数量的行
  // 不必一次读取所有行
  for (let i = 0; i < 100; i += 1) {
    console.log(readLine())
  }

  // readLine 工厂函数
  async function createReader(stream) {
    // 当前字节
    let bytes = ''

    // 等待流加载并可读
    await new Promise(r => stream.once('readable', r))

    // 返回 readLine 函数
    return {
      readLine() {
        let index
        // 当前字节中没有换行符时
        while ((index = bytes.indexOf('\n')) === -1) {
          // 从流中读取一些数据
          const data = stream.read()
          // 如果数据为 null,意味着文件结束了
          if (data === null) {
            // 如果没有剩余字节,只需返回 null
            if (!bytes) return null
            // 如果还有一些剩余字节,则返回它们并清空字节
            const rest = bytes
            bytes = ''
            return rest
          }
          bytes += data
        }
        // 获取到换行符为止的字符
        const line = bytes.slice(0, index)
        // 从当前字节中移除第一行
        bytes = bytes.slice(index + 1)
        // 返回第一行
        return line
      }
    }
  }
})()

如果你有任何问题,请随时提出。

英文:

I've made a short function which should do what you want

const { createReadStream } = require(&#39;fs&#39;);
// wrapping everything in async function so await can be used
// not needed when global await is available
(async () =&gt; {
// create readable stream
const stream = createReadStream(&#39;lorem.txt&#39;, { encoding: &#39;utf-8&#39; })
// get readLine function instance
const { readLine } = await createReader(stream)
// read 100 lines, you can read as many as you want
// don&#39;t have to read all at once
for (let i = 0; i &lt; 100; i += 1) {
console.log(readLine())
}
// readLine factory
async function createReader(stream) {
// current bytes
let bytes = &#39;&#39;
// await for stream to load and be readable
await new Promise(r =&gt; stream.once(&#39;readable&#39;, r))
// return readLine function
return {
readLine() {
let index
// while there is no new line symbol in current bytes
while ((index = bytes.indexOf(&#39;\n&#39;)) === -1) {
// read some data from stream
const data = stream.read()
// if data is null it means that the file ended
if (data === null) {
// if no bytes left just return null
if (!bytes) return null
// if there are some bytes left return them and clear bytes
const rest = bytes
bytes = &#39;&#39;
return rest
}
bytes += data
}
// get characters till new line
const line = bytes.slice(0, index)
// remove first line from current bytes
bytes = bytes.slice(index + 1)
// return the first line
return line
}
}
}
})()

huangapple
  • 本文由 发表于 2023年1月4日 01:24:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/74996635.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定