C ++在具有不同数据类型的列式存储中读取CSV表

时间:2016-03-15 14:36:05

标签: c++ arrays pointers import-from-csv

我想读取包含数据库表(TPCH)的CSV文件。每个文件都有不同数量的列,行和数据类型。

例如:

 file1: Int, double, char[]
 file2: double, char[], int, int 

另一个要求是每列应该驻留在一个数组中(对于每一列,一个数组 - 不是每行)。

我的解决方案: 目前我在运行时使用new创建数组,具体取决于数据类型和csv文件的大小

 e.g. file1: would be int[] , double[]... 

然后我将数组的起始地址存储为map *中的void *(int,void *)。

当我想从数组中读取值时,我必须检索void *并根据类型进行转换。

正如你所看到的,我有很多指针和铸造,这是顽皮的。是否有更好的方法以Columnar格式存储表?我想使用数组,因为我经常复制它们并通过网络传输它们。另外,我不想使用升级库。

2 个答案:

答案 0 :(得分:0)

是的,指针往往导致头痛的头脑。首先,我建议你使用STL容器,例如std::vector,它会让你的生活更轻松。不需要提升,甚至不需要新的C ++编译器,因为std::vector很长一段时间都在这里。

但我不明白为什么要存储数组的起始地址。无论如何,如果您只想存储地址,可以使用标题文件<cstdint>并使用类型intptr_t / uintptr_t,以保证能够保存void*

答案 1 :(得分:0)

这是variant的一个很好的用例。在C ++ 17中,我们将此作为标准库的一部分,但是现在我们仍然使用boost实现。

如果您不想使用boost,可以选择几种方式,但它们至少有点粗略。

  1. void*。出于多种原因,这是不可取的。你知道我已经在这里钻研了。
  2. union。在处理具有构造函数和析构函数的对象时,这也是不可取的。你必须记住调用析构函数,你必须知道调用构造函数到位。优于void*,但只是勉强。假设你正在处理所有原始类型,std::vector<some_union_type>可能不会那么糟糕,但是一旦你引入动态大小的字符串,你就会陷入伤害的世界。
  3. 字节操作。将所有内容存储在char[](更具体地说,std::vector<char>)中,并在某种枚举中保留有关数据类型的元数据。使用该枚举将字节转换为正确的类型。这是一个非常多毛的解决方案,可以手工拼凑,但它与variant通常的实现类似。
  4. 运行时多态性。创建父类,然后为每种数据类型创建子类。动态分配子类(将它们存储在std::unique_ptr中)并通过执行dynamic_cast将它们取出,直到获得正确的类型(或将数据类型存储在枚举中并根据该类型进行转换)。这可能是最高级别的#34;解决方案,并且可能比前三个解决方案更容易实现。
  5. 基于概念的多态性。这基本上是手工编制any的特例(在另一个答案中提到)。 Sean Parent涵盖here。对于您的情况,您可能会发现自己实现类似variant::visitor模式的内容以获取所需的数据。
  6. 或许使用boost::variant看起来并不那么糟糕。 ;)