将 json 文件转储为二进制文件的形式

问题描述 投票:0回答:1

我有一个非常大的json文件,可能接近1.5GB,有点像

的格式
[
  {
    "a": 123,
    "b": 143,
    "c": "111",
    "d": 0,
    "e": 0
  },
  {
    "a": 1455,
    "b": 1899,
    "c": "1334",
    "d": 0,
    "e": 0
  }
]

所以我想找到一种方法将其转换为二进制形式并有效地读取此 json 文件内的数据。我可以知道使用 Scala 实现这一目标的任何方法吗?

json scala binary compression dump
1个回答
0
投票

我将给您一个可能的答案,然后详细介绍选择序列化格式的详细信息,希望这可以作为考虑您可能了解的更大情况的指南。

存在多种二进制序列化格式,每种格式都有自己的优点和缺点需要考虑,这就是为什么给你“一个正确的答案”甚至不值得尝试。

我可以给您的一个建议是评估 Apache Avro,这是一种广泛使用的二进制格式,通常与 Apache Kafka 和一般大型数据处理系统相关。

这是一个简短的示例,说明如何使用 Circe 解析原始 JSON 文件,然后使用 avro4s 序列化为 Avro:

import io.circe.generic.auto._, io.circe.syntax._
import io.circe._, io.circe.parser._

final case class Item(a: Int, b: Int, c: String, d: Int, e: Int)

val items = parse(json).flatMap(_.as[Vector[Item]]).toTry.get

import com.sksamuel.avro4s._

val schema = AvroSchema[Item]
val baos = new java.io.ByteArrayOutputStream()
val os = AvroOutputStream.data[Item].to(baos).build()
os.write(items)
os.flush()
os.close()
baos.close()

您可以在 Scastie 上使用此代码。请注意:

  1. 我将
    json
    作为
    lazy val
    保留在游乐场的末尾,因为 Avro 需要将数据模式与数据本身一起存储,这意味着对于几个对象来说,自描述 JSON 格式实际上更紧凑,所以我需要包含更多内容以确保我没有歪曲该格式的优点和缺点
  2. 这里我序列化为字节数组,以便我链接的在线游乐场让您了解使用二进制格式可以实现的节省,实际上您很可能会写入某种持久存储

如上所述,上面的答案是一种可能的答案。实际上,选择一种数据序列化格式并不是一件小事,需要充分了解所涉及的权衡,考虑到一旦选择一种格式,根据所涉及的系统,迁移它可能是一项漫长、困难且有风险的操作。

如果您感兴趣的只是节省空间,您可能想看看简单地压缩 JSON 是否适合您,因为您知道这会将空间节省转化为计算时间,否则这些时间可能会花在其他方面。如果文件的结构非常可预测,则压缩的 JSON 文件可能能够与压缩的二进制文件竞争。 JSON 在工具可用性和检查文件本身的能力方面具有许多优势,除了文本编辑器之外无需任何专用工具。

如果您仍然确信要转向二进制序列化格式,则存在许多出于特定需要而诞生的格式,您可能需要一一研究它们以评估它们是否适合您的项目。我将列出一些最广泛使用的:

  • 阿夫罗
  • 协议缓冲区
  • 节俭
  • 平面缓冲区
  • Cap'n'proto
  • BSON
  • 镶木地板
  • CBOR
  • 消息包

维基百科上的此页面可能会帮助您开始了解每种语言的一些特征。您可能想问自己的几个问题是:

  • 我的团队使用的语言有哪些类型的支持?
  • 通常如何使用该格式以及为什么?
  • 该格式如何让我思考模式演变和向后/向前兼容性?
  • 格式是自描述的还是需要引用外部存储的模式?
© www.soinside.com 2019 - 2024. All rights reserved.