在说任何话之前,我不得不说,尽管我是一名经验丰富的 Java 程序员,但我对 C/C++ 编程还是比较陌生。
我必须以一种可以从不同操作系统和平台访问的格式保存二进制文件。它应该非常有效,因为我必须处理大量数据。我应该为此调查什么方法?主要优点和缺点是什么?
在说任何话之前,我不得不说,尽管我是一名经验丰富的 Java 程序员,但我对 C/C++ 编程还是比较陌生。
我必须以一种可以从不同操作系统和平台访问的格式保存二进制文件。它应该非常有效,因为我必须处理大量数据。我应该为此调查什么方法?主要优点和缺点是什么?
网络顺序(big-endian)是一种事实上的标准。但是,如果您的程序主要用于x86(小端),出于性能原因,您可能希望坚持使用该协议(该协议仍可在大端机器上使用,但它们反而会对性能产生影响)。
除了htonl(转换 32 位值)之外,还有 htons(16 位)和 bswap_64(64 位非标准)。
如果您想要二进制格式,但又想抽象出一些细节以简化序列化和反序列化,请考虑使用Protocol Buffers或Thrift。协议缓冲区是可更新的(您可以在不破坏现有代码的情况下向模式添加可选或重复(0 或更多)字段);不确定节俭。
但是,在过早优化之前,请考虑解析是否真的是瓶颈。如果读取文件的每一行都需要数据库查询或计算,那么您可以使用更具可读性的格式,而不会产生任何明显的性能影响。
我认为这种任务有几个不错的选择。
在大多数情况下,我的首选可能是 Sun(现在是 Oracle)的 XDR。它在 Sun 的 RPC 实现中使用,因此经过相当长一段时间的大量测试。它在RFC 1832中定义,因此文档广泛可用。还有一些库(便携式和其他)知道如何转换为/从这种格式转换。在线表示相当紧凑,转换相当有效。
XDR 最大的潜在问题是您确实需要知道数据代表什么才能对其进行解码 - 即,您必须(通过某些外部手段)确保发送者和接收者就(例如)结构的定义达成一致在接收者可以(轻松)了解正在发送的内容之前,他们将通过电线发送。
如果您需要创建一个完全自描述的流,那么有人可以仅根据流本身的内容来判断它包含的内容,那么您可以考虑使用 ASN.1。它在某些方面很粗鲁和讨厌,但它确实产生了自我描述的流,被公开记录,并且被广泛使用(尽管主要在相当有限的领域中)。有相当多的库可以实现编码和解码。我怀疑是否有人真的很喜欢它,但如果你需要它的功能,它可能是第一选择,如果只是因为它已经为人所知并在某种程度上被接受。
对于这种情况,我的第一选择是 ASN.1,因为它使您可以灵活地在任一端使用所需的任何编程语言,并且独立于平台。它向您隐藏了字节序问题,因此您不必担心它们。一端可以使用 Java,而另一端使用 C 或 C++ 或 C#。它还支持多种编码规则,您可以根据需要从中选择。如果目标是使编码尽可能小,则有 PER(打包编码规则);如果您更喜欢使用 XML 交换信息,则有 E-XER(扩展 XML 编码规则),或者有 DER(区分编码规则)如果您的应用程序涉及数字签名或证书。ASN.1 广泛应用于电话领域,也应用于银行、汽车、航空、医疗设备等多个领域。
您可以免费试用 ASN.1 的一个极好的资源是http://asn1-playground.oss.com,您可以在其中使用一些现有的 ASN.1 规范,或者尝试创建自己的规范,看看各种编码规则会产生什么。
有一些优秀的书籍可从http://www.oss.com/asn1/resources/books-whitepapers-pubs/asn1-books.html免费下载,其中第一本名为“ASN.1 — 异构之间的通信”系统”。