C++ 的“最佳”输入文件格式? [关闭]
Posted
技术标签:
【中文标题】C++ 的“最佳”输入文件格式? [关闭]【英文标题】:"Best" Input File Formats for C++? [closed] 【发布时间】:2013-01-19 22:12:16 【问题描述】:我正在着手开发一款新软件,该软件最终需要一些强大且可扩展的文件 IO。那里有很多格式。 XML、JSON、INI 等。然而,总有优缺点,所以我想我会征求一些社区意见。
以下是一些粗略的要求:
-
格式是“标准”...如果我不需要,我不想重新发明***。它不一定是正式的 IEEE 标准,但作为新用户,您可以通过谷歌搜索并获取一些信息,可能有一些超出 vi 的支持工具(编辑器)。 (尽管软件用户通常会精通计算机并乐于使用 vi。)
与 C++ 轻松集成。我不想使用 100mb 的库和三个不同的编译器来启动和运行它。
支持表格输入(二维、n 维)
支持 POD 类型
可以在需要更多输入时进行扩展,很好地绑定到变量等。
解析速度并不是很重要
理想情况下,写(反映)和读一样容易
在 Windows 和 Linux 上运行良好
支持合成(一个文件引用另一个要读取的文件,依此类推。)
人类可读
在一个完美的世界里,我会使用一个仅包含标头的库或一些干净的 STL 实现,但如果它运行良好,我可以使用 Boost 或一些小型外部库。
那么,您对各种格式有何看法?缺点?优势?
编辑
要考虑的选项?还有什么要补充的吗?
XML YAML SQLite Google 协议缓冲区 Boost 序列化 INI JSON【问题讨论】:
您要表示什么类型的数据?仅限英语,还是 i18n 有问题?有一个紧凑的表示有多重要?需要与其他语言互操作? 对于文本格式:XML - with 适当的库。 INI 在层次/维度数据和 JSON 上失败了,虽然从 javascript 中使用起来非常好,但缺少一些好的特性和 XML 工具。 C++ 不直接支持结构化文件。您总是需要一段代码来解析或生成比纯二进制或文本文件更复杂的东西。 XML/JSON 是一个不错的选择,您可以通过赋予事物特殊含义来扩展它们。但是,您必须意识到,当您拥有大量数据时,任何格式在纯文本编辑器中的可读性都会变得很差。 @vonbrand - 是的。仅限英语。数据将是配置数据,但本质上主要是数字。最复杂的数据是大约 1024x1024x1024 元素的表格。 INI 的一些变体也许就足够了?取决于数据结构的复杂程度... 【参考方案1】:有一种出色的格式可以满足您的所有标准:
SQLite!
请阅读 article 关于使用 SQLite 作为应用程序文件格式的信息。另外,请由 D. Richard Hipp(SQLite 作者)watch Google Tech Talk 讨论这个主题。
现在,让我们看看 SQLite 如何满足您的要求:
格式是“标准”
SQLite 已成为大多数移动环境和许多桌面应用程序(Firefox、Thunderbird、Google Chrome、Adobe Reader 等等)的首选格式。
轻松与 C++ 集成
SQLite 有standard C interface,只有一个源文件和一个头文件。有C++ wrappers too。
支持表格输入(2d、n 维)
SQLite 表就像您想象的那样是表格的。要表示 3 维数据,请创建包含 x,y,z,value
列的表并将您的数据存储为一组行,如下所示:
x1,y1,z1,value1
x2,y2,z2,value2
...
支持 POD 类型
我假设 POD 是指普通旧数据或 BLOB。 SQLite 允许您按原样存储 BLOB 字段。
可以根据需要进行更多输入扩展,很好地绑定到变量
这是它真正闪耀的地方。
解析速度并不是很重要
但是 SQLite 的速度非常棒。其实解析基本上是透明的。
理想情况下,写(反映)和阅读一样容易
只需使用INSERT
写作和SELECT
阅读 - 还有什么比这更容易的呢?
在 Windows 和 Linux 上运行良好
您打赌,所有其他平台也是如此。
支持合成(一个文件引用另一个文件读取)
您可以将一个数据库附加到另一个数据库。
人类可读
不是二进制的,但是有很多优秀的 SQLite 浏览器/编辑器。我喜欢 Windows 上的 SQLite Expert Personal 和 Linux 上的 sqliteman。还有SQLite editor plugin for Firefox。
SQLite 免费为您提供的其他优势:
数据是可索引的,这使得搜索速度非常快。使用 XML、JSON 或任何其他纯文本格式是无法做到这一点的。
即使数据量非常大,也可以部分编辑数据。您不必为了编辑一个值而重写几 GB。
SQLite 完全是事务性的:它保证您的数据在任何时候都是一致的。即使您的应用程序(或整台计算机)崩溃,您的数据也会在下次首次尝试连接到数据库时自动恢复到上次已知的一致状态。
SQLite 存储您的数据逐字记录:您无需担心转义数据中的垃圾字符(包括字符串中嵌入的零字节) - 只需始终使用 prepared statements,即使其透明所需的一切。在处理文本数据格式(尤其是 XML)时,这可能是一个大而烦人的问题。
SQLite 以 Unicode 存储所有字符串:UTF-8
(默认)或UTF-16
。换句话说,您无需担心文本编码或数据格式的国际支持。
SQLite 允许您以小块(实际上是逐行)处理数据,因此它在低内存条件 中运行良好。这对于任何基于文本的格式都是一个问题,因为它们通常需要将所有文本加载到内存中来解析它。诚然,市面上很少有高效的基于流的 XML 解析器,但总的来说,与 SQLite 相比,任何 XML 解析器都会非常消耗内存。
【讨论】:
谢谢。这是很好的输入。我会检查更多! SQLite 好像不支持任意大小的数组。 SQLite 表是你的任意大小的数组,不是吗? 我可以推荐 codesynthesis.com/products/odb 作为一个好的 SQLite 包装器吗?【参考方案2】:在使用 XML 和 json 进行了大量工作后,以下是我对两者作为可扩展序列化格式的相当主观的看法:
格式是“标准”:两者都可以 与 C++ 轻松集成:两者都支持。在每种情况下,您可能最终都会使用某种库来处理它。在 Linux 上,libxml2 是一个标准,而 libxml++ 是它的 C++ 包装器;您应该能够从发行版的包管理器中获得这两个。让那些在 Windows 上工作的人需要一点点努力。 Boost 中似乎对 json 有一些支持,但我没有使用过;我一直使用库来处理 json。确实,图书馆的路线对任何一方来说都不是很繁重。 支持表格输入(二维、n 维):两者都支持 支持 POD 类型:两者都支持 可以在需要更多输入时进行扩展:两者都可以,这对他们来说都是一大优势。 很好地绑定到变量:如果您的意思是在文件本身内部以某种方式说“此 条数据必须在我的程序中自动反序列化为 this 变量",那么两者都不是。 编写(反映)和阅读一样容易:取决于您使用的库,但根据我的经验,两者都可以。 (您实际上可以使用 printf() 完成编写 json 的工作。) 在 Windows 和 Linux 上运行良好:两者都可以,同样适用于 Mac OS X。 支持一个文件引用另一个文件来读取:如果您的意思类似于 C #include,那么 XML 具有执行此操作的能力(例如文档实体),而 json 则没有。 人类可读:两者通常都以 UTF-8 编写,并且允许换行和缩进,因此可以是人类可读的。但是,我刚刚处理了一个 479 KB 的 XML 文件,它全部在一行上,所以我必须通过漂亮的打印机运行它才能理解它。 json 也可能很难读取,但根据我的经验,它的格式通常比 XML 更好。开始新项目的时候,我一般比较喜欢json;它更紧凑,更易于阅读。我可能会选择 XML 而不是 json 的主要原因是如果我担心收到格式错误的文档,因为 XML 支持自动文档格式验证,而您必须使用 json 编写自己的验证代码。
【讨论】:
这是很好的信息。我过去主要使用XML,但发现表格输入很尴尬。 “支持一个文件引用另一个文件来读取:如果你的意思类似于 C#include,那么 XML 有一些能力做到这一点(例如文档实体),而 json 没有。”很高兴知道这一点,令人惊讶,并且可能排除了 JSON。 我发现在 JSON 上使用 XML 的一些好处:Schemas/validators/infosets、XPath/XQuery、数据库(例如 SQL Server)支持、命名空间、属性 和 子元素。不,不,我不会说 XSLT 1.0 - 它会永远消失:D JSON 非常适合 REST、Web 服务、JavaScript 集成和“小文档”。然而,这种简单性是以标准化高级功能和工具为代价的——并非所有“企业”的东西都必须难以使用,即使许多基于 XML 的产品都是如此。 @pst:关于 json 可读性的更正。【参考方案3】:查看google buffers。这可以满足您的大部分要求。
From their documentation,高级步骤是:
在 .proto 文件中定义消息格式。 使用协议缓冲区编译器。 使用 C++ 协议缓冲区 API 来写入和读取消息。
【讨论】:
您有使用 Google proto 缓冲区的经验吗?我的感觉是,很难扩展消息并保持向后兼容性,但我还没有与他们一起实施任何解决方案,以了解对于具有潜在大量输入的大型项目(从几十个到数百个文件组成一个输入)维护它们的难易程度设置)。 看起来 proto 缓冲区不支持 n 维数组。 link @DigitalInBlue 我确实对谷歌缓冲区有一些经验。我在一个研发项目中使用它们来远程控制一个硬件。 Updating A Message Type, search for section with the same name, 非常简单,但需要一些,我会考虑不要尽可能频繁地使用 required 关键字。至于 N 维数组,您提供的链接说明了一种很好的模拟它们的方法。你为什么不想按照他们的建议去做呢? 感谢您的信息。我没有理由不按照建议去做,只是想在做出决定之前尝试了解各种标准的来龙去脉。 proto 缓冲区中的“模拟”并不理想,但可能不会破坏交易。【参考方案4】:出于我的目的,我认为要走的路是 XML。
-
格式是一种标准,但允许对架构进行修改和灵活性,以便随着程序要求的发展而变化。
有几个库选项。有些较大 (Xerces-C) 有些较小 (ezxml),但有很多选择,因此我们不会局限于单一提供商或非常具体的解决方案。
它可以支持表格输入(2d,n维)。这需要在“我们的”端进行更多的解析工作,这可能是 XML 的最薄弱环节。
支持 POD 类型:绝对支持。
可以根据需要更多输入进行扩展,通过架构修改和解析器修改很好地绑定到变量等。
解析速度并不是很重要,因此处理一个或多个文本文件不是问题。
XML 可以通过编程方式编写,就像阅读一样容易。
在 Windows 和 Linux 或任何其他支持 C 和文本文件的操作系统上运行良好。
支持合成(一个文件引用另一个要读取的文件,依此类推。)
人类可读的许多文本编辑器(Sublime、vi 等)支持开箱即用的语法突出显示。许多网络浏览器都能很好地显示数据。
感谢大家的好评!我认为如果我们想要一个纯粹的二进制解决方案,Protocol Buffers 或 boost::serialization 可能是我们应该采用的方式。
【讨论】:
虽然我没有对此投反对票,但我会评论:在 SO,由于您的答案没有提供其他答案未涵盖的解决方案,因此将您所做的事情写成答案是一种不好的形式并接受。最好接受其他人的最佳答案(我认为你仍然可以改变),除非它们都没有任何好处......另外,除非你的答案实际上增加了一些有用的东西(这没有),最好写你选择的解决方案作为评论。 我确实投了反对票。自己写答案,有效地抄袭别人的答案,然后接受它作为答案,这种形式真的很糟糕,它不利于这里的激励机制。以上是关于C++ 的“最佳”输入文件格式? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
为 Kindle 格式化 LaTeX 源代码的最佳方法是啥? [关闭]
C++笔记--Linux编程-linux文件和输入输出 文件和目录操作