【问题标题】:Best practice for reading csv (with variable number of lines) into data structures将 csv(行数可变)读入数据结构的最佳实践
【发布时间】:2010-08-16 21:02:52
【问题描述】:

我正在编写一个小程序来读取具有可变行数的 csv,并且对最佳实践有疑问:

为每一行的数据创建存储以创建一个包含 csv 数据结构的数组(每行一个 csv)的最佳方法是什么?

分配给数组的大小可以设置为一个很大的数字(例如,比 csv 中合理的行数更多)? 我在网上的很多例子中都看到了这一点。

或者...是否有一种聪明的方法来判断需要多少空间,例如预先计算行数或通过使用链表而不是数组来动态添加空间静态存储分配。有什么最佳实践吗?我不认为选择一个随机数看起来很巧妙......

任何想法将不胜感激。

【问题讨论】:

  • 如果您需要有关使用数据结构的建议,请提供少量有关您计划如何处理 csv 数据的信息。但是是的,你是对的,选择随机数不是一个好主意。
  • 基本上我知道我已经创建了一个适合 CSV 行本身的数据结构(一旦解析),但我问的是正确或常用的数据结构保存这些行,因为它们正在被读取,这些行的长度会随着文件长度的增加或减少而变化。
  • 我希望从你那里得到一些东西,让我可以建议使用 sed 和 awk 进行文本处理,但我不能这样做,因为 1)你可能需要跨平台2)我没有看到你需要它的任何证据。 :( 所以你接受的答案是好的。尽量避免一次读取整个文件。如果你读取一个巨大的文件并且需要为所有文件分配空间空间,你可能会用完堆空间。

标签: c csv data-structures


【解决方案1】:

两个最佳实践:

  1. 永远不要期望来自外部的输入会更正。
  2. 使其具有事务性(全部导入或回滚)
  3. 如果可能,利用像 http://www.codeproject.com/KB/database/CsvReader.aspxhttp://sourceforge.net/projects/javacsv/ 这样的第三方 API 或库来大大减少重新发明轮子。如果你坚持使用 C 并且可以使用 C++ 考虑这种方法:How can I read and manipulate CSV file data in C++?

【讨论】:

  • 这很有帮助......但并没有真正解决问题的数据结构部分。谢谢。
  • 通过 C++ 中类似问题的链接查看它的最后。至于分配,您可能希望设置一个默认的 alloc 和 realloc,因为它已超出。但是,您最好使用 C++ 示例中的集合,这意味着分配是在幕后处理的。
  • 嗯,只是在这里很有趣,但是:#1 肯定是正确的,但与问题无关。 #2 可能正确也可能不正确,具体取决于问题,但同样,与问题并不真正相关。
【解决方案2】:

如果您可以在读取数据时对其进行处理,而不是将其全部保存并在之后处理,这将消除问题。

我避免先计算行数,因为这需要读取整个文件两次。我想如果文件很小,效率影响不大,但是如果您知道文件很小,那么您可以分配足够大的空间。

所以总的来说,我的方法——如果我不能一次处理一行文件——是使用一种可以增长的数据结构,比如链表。然后对于每一行,我只分配一个新块。根据您的工作,您可能会使用动态数组:分配应该足以满足正常情况的空间量。如果填满,分配更大的空间,将第一个复制到第二个,删除第一个,然后继续处理第二个。如果您填写,请重复该过程。这可能是大量的数据移动,但最终使用的空间量将少于链表,因为您没有指针,并且遍历会更快,因为您没有追逐指针并且可能正在运行遍布虚拟内存。

【讨论】:

  • 注意对于"分配更大的空间,复制第一个到第二个,删除第一个"你可以使用realloc()函数——这正是它的预期用途(有时甚至可以避免复制)。
  • @caf:坦率地说,我已经忘记了 realloc ——我最近很少做 C 语言。如果您要使块显着变大,我猜它几乎总是必须分配新空间并释放旧空间。只有在原始分配上恰好有可用空间“接壤”时,它才能避免这种情况。但重点是,这可能是“正确”的做法。
【解决方案3】:

真的没有“最佳实践”。请记住数据的特定结构,读取、存储、查询、排序、查找/消除/忽略重复数据等的速度。树、链表、散列、有序数据等. 是不错的选择,具体取决于我已经提到的因素。

我同意其他人的看法。无需重新发明轮子。必须有大量关于如何解析 CSV 的样本。

但是,在选择您最喜欢的库时,请注意以下几点:

  1. 最佳实践:永远不要假设数据具有特定(小或非常大)的数据量。推论:不要将所有数据存储在内存中,尽可能少,并假设无论您的数组大小如何,数据都可能比它大。考虑到这一点,请绕过该假设。
  2. 另一个最佳实践:测试极端情况(无输入、非常大的输入、只有一行或一个元素等)
  3. CSV 文件不是标准文件。例如,一些生成 CSV 的程序会忽略以下情况:

3.1。字符串中的逗号。例如,它与“Smith, John”不是同一个“Smith, John”。 3.2.带有字符串的特殊字符,例如撇号、制表符或引号。他们是如何处理的?例如,Microsoft 通常使用双双引号来表示字符串中的引号。 3.3.当然,还要注意行尾格式(Unix 或 Windows 风格)。

请务必查看大量实际数据。永远不要相信用户(也不相信程序员 :-)。

祝你好运。路易斯。 Excel和Visual Basic用来生成

【讨论】:

    【解决方案4】:

    使用库或事先计算行数。您还可以使用某种列表数据结构来避免担心行数。

    +1 感谢 Nissan Fan 推荐了一个库,在我看来,除非你想学习很多关于 CSV 解析和 CSV 解析边缘案例的知识,否则这总是要走的路。

    【讨论】:

    • 感谢您的回复,这基本上是我上面列出的两种替代方法。我想知道为什么网络上的所有示例都支持这种任意数组大小的方法。对我来说似乎很草率。
    猜你喜欢
    • 2016-09-21
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-02
    • 2011-09-24
    • 2021-08-28
    • 2018-07-17
    相关资源
    最近更新 更多