【问题标题】:c++ reading formated tabulated data from file using BOOST / STL/ etcc ++使用BOOST / STL /等从文件中读取格式化的表格数据
【发布时间】:2011-02-24 13:22:19
【问题描述】:

对我来说,为表格文本文件创建格式化数据读取/写入函数的最佳方式是什么。说一些电话,例如:

readElement(i,j)

insertRow(elem[])

readColHeaders()

我想知道是否有任何现有的包装器可以做到这一点?

内部格式是制表符间隔数据或 CSV。

Thnx-Egon

【问题讨论】:

    标签: c++ boost stl


    【解决方案1】:

    有很多 csv 阅读器,但我从来没有找到好的东西。

    最简单的方法是使用 boost::tokenize 从你的文件中填充一个向量>。一种更好的方法是使用 boost::spirit(但学习曲线就像过山车一样)。

    要生成 sur 文件,迭代向量> 非常简单。

    【讨论】:

      【解决方案2】:

      对于 C 或 C++,没有“标准”的 csv 读取器/写入器。这并不意味着你不能找到一些预先存在的库代码来使用,但是没有一个库来统治它们。在我的工作中,我们大量使用 csv 文件,所以我继续使用自己的文件,以便尽可能适合我的工作流程。如果你也想做自己的事情,我可以告诉你我在图书馆里做过的一些事情,效果相当不错:

      • 我将数据保存为 boost::any 向量的向量。我让用户在构造函数中指定数据的格式,类似于将格式传递给 scanf 的方式。这使用户不必进行自己的演员表。我使用 boost::tokenize 和 boost::lexical_cast 来进行实际的拆分和转换。如果您的 csv 文件无法放入内存,这显然不会很好,但这对我来说很少有问题。

      • 我可以有一个模板化的 get() 来执行 any_cast 并返回正确的数据。

      • 我有一个列名哈希到它们的索引,以便支持按列名查找,而不仅仅是位置查找

      • 我允许用户指定某些列组合的“主键”,然后保留一个散列,这样对于每一行,您都有一个键 -> 行号中的值的映射。例如,如果您正在阅读股票数据,您可能希望根据 CUSIP 或股票代码来查找行,而不是遍历整个数据来查找您的行。

      • 让用户指定大小提示,以便您可以在存储中保留()

      • 让用户指定回调函数,以便他可以在您读/写时处理和过滤他不想要的行

      • 允许用户指定文件在读/写时是否需要锁定

      • 允许用户为文件中没有标题的文件传入自己的列标题

      不要进入语言辩论,但这个库实际上是我最初在 perl 中所做的一些东西的移植,如果它不是在 perl 中编写起来容易 10 倍,用户友好度提高 10 倍,那该死的。如果可以的话,我不建议在 C++ 中进行 csv 处理。

      【讨论】:

        【解决方案3】:

        要将制表符分隔的表格读入字符串向量的向量...

        #include <vector>
        #include <string>
        #include <sstream>
        #include <iostream>
        
        typedef std::vector<std::string> StringVec;
        typedef std::vector<StringVec> RowVec;
        
        RowVec readRows(std::istream& f) {
            std::string line;
            RowVec rows;
            while (std::getline(f, line)) {
                rows.push_back(StringVec());
                std::string entry;
                std::istringstream linestrm(line);
                while (std::getline(linestrm, entry, '\t')) {
                    rows.back().push_back(entry);
                }
            }
            return rows;
        }
        
        int main() {
            std::istringstream textFile("a\tb\tc\n1\t2\t3");
            RowVec rows = readRows(textFile);
            std::cout << rows.size() << std::endl;
            std::cout << rows[0][0] << std::endl;
            std::cout << rows[1][2] << std::endl;
            return 0;
        }
        

        【讨论】:

          【解决方案4】:

          如果您的数据很小(例如小于几百兆字节),我会将整个文件读入内存。为此,您可以将其存储在像boost::numeric::ublas::matrix&lt;std::string&gt; 这样的字符串矩阵或像std::vector&lt;std::vector&lt;std::string&gt; &gt; 这样的向量向量中

          Boost.Spirit 提供了一种非常好的方法来将这种类型的文本数据解析为这些结构。这归结为一个解析命令,如:

          boost::spirit::qi::phrase_parse(
              begin,
              end, 
              // parse rule:
          
                  *(char_ - '\t') % '\t' 
          
              // end parse rule
              space,
              vec);`
          

          更多精神例子在这里:http://www.boost.org/doc/libs/1_46_0/libs/spirit/doc/html/spirit/qi/tutorials.html

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2023-03-31
            • 2017-08-06
            • 1970-01-01
            • 1970-01-01
            • 2011-11-18
            • 2012-05-03
            • 1970-01-01
            相关资源
            最近更新 更多