【问题标题】:Node.js: Reading long JSON file always cuts last closing bracket characterNode.js:读取长 JSON 文件总是剪切最后一个右括号字符
【发布时间】:2021-07-05 07:39:28
【问题描述】:

我有以下:

let base64strings = ["U2FsdGVkX1+lWCC8X04S/duu480r0BkPvea...", ....]

let writableStream = fs.createWriteStream('test.json')
let index = 0

for (const base64string of base64strings) {
  writableStream.cork()

  let textForStream = ''

  if (index === 0) {
    textForStream += '['
  } else {
    textForStream += ','
  }

  textForStream += JSON.stringify({ index, data: base64string })

  if (index === (base64strings.length - 1)) {
    textForStream += ']'
  }

  writableStream.write(textForStream)

  writableStream.uncork()

  index++
}

let check = fs.readFileSync('test.json', { encoding: 'utf-8' })

let arr = JSON.parse(check) // <--- this breaks with a *SyntaxError: Unexpected end of JSON input*

这是因为check 的最后一个字符应该是] 现在丢失了。每次我读取文件时它都会被切断,即使当我打开它时它在 test.json 中。

但是,如果我随后在编辑器中打开 test.json,一切看起来都很好:

[{"index":0,"data":"U2FsdGVkX1+lWCC8X04S/duu480r0BkPvea..."},{"index":1,"data":"U2FsdGVkX1+lWCC8X04S/duu480r0BkPvea..."}, ...]

我做错了什么?

{ encoding: 'utf-8' }搞砸了,但我不知道如何解决这个问题。

【问题讨论】:

  • 为什么不创建带有编码的写入流呢?
  • 为什么在第一个工作场景中不需要这样做?不过我会试试的。
  • 您可能还想阅读 Node 的 advice on Buffering,这很可能是您的问题所在。在读取之前,您需要等待缓冲区写入文件系统。该页面充满了有关流 API 的信息。
  • 我实际上在一个循环中创建了多个“write.()”,但为了便于阅读,我省略了它。我将更新 OP。我想我需要在每个循环结束时等待“排水”。

标签: javascript node.js json utf-8 base64


【解决方案1】:

我删除了cork()uncork() 调用,现在我在每个循环之后等待drain,它可以工作:

function forDrain(stream) {
  return new Promise((resolve) => {
    stream.once('drain', resolve)
  })
}

let base64strings = ["U2FsdGVkX1+lWCC8X04S/duu480r0BkPvea...", ....]

let writableStream = fs.createWriteStream('test.json')
let index = 0

for (const base64string of base64strings) {   
  let textForStream = ''

  if (index === 0) {
    textForStream += '['
  } else {
    textForStream += ','
  }

  textForStream += JSON.stringify({ index, data: base64string })

  if (index === (base64strings.length - 1)) {
    textForStream += ']'
  }

  writableStream.write(textForStream)

  await forDrain(writableStream)
    
  index++
}

writableStream.end()

let check = fs.readFileSync('test.json', { encoding: 'utf-8' })

console.log(JSON.parse(check).join('') === base64strings.join('')) // true

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-23
    • 2015-07-29
    • 2012-12-02
    相关资源
    最近更新 更多