使用C ++解析巨大的csv文件

时间:2017-01-03 08:59:15

标签: c++ stl

我命令模拟我的网络我正在使用大小在5到30 GB之间的跟踪文件(csv文件)。 csv文件是基于行的,其中每行包含由空格分隔的多个字段,并形成信息以形成网络数据包:

3     53      4    12    1     1  2  6

由于文件的大小可以达到几GB(数百万行),最好将它分成小块myfile00.csv,myfile01.csv ...,或者我可以处理整个文件没有被加载到内存中的硬盘? 我想在特定时间逐行读取文件,这是模拟的时钟周期,并获取行中的所有信息以创建omnet ++消息。

packet MyTrace::getpacket() {
int id; // first field
int cycle; // second field
int source; // third field
int destination; // fourth field
int numberofDep; // fifth field
std::list<int> listofDep; // remaining fields

if (!traceFile.is_open()) {
 // get id
 // get cycle
 // ....
}

任何建议都会有所帮助。

编辑:

  string line;
  ifstream myfile ("BlackSmall.csv");
    int currentline=0 ;
  if (myfile.is_open())
  {
   while (getline(myfile, line)) {  

      istringstream ss(line);
      string request;
      int id, cycle, source , dest, srcType, destType, packetSize, dependency;
      int listdep;
      std::list<int> dep; 
              ss >> id; 
              ss>> cycle; 
              ss>> source; 
              ss>> dest;
              ss>>request;
              ss>> srcType;
              ss>> destType;
              ss>> packetSize;
              ss>> dependency; 
              while (ss >> listdep) dep.push_back(listdep);
           // Create my packet

    }
    myfile.close();
    }
  else cout << "Unable to open file"; 

通过上面的代码,我可以从一行获得我需要的所有信息。 问题是我需要在一个类中使用这个代码,当我调用它时只返回一行的信息。当我打电话给这个班级时,有没有办法指向一个特定的行?

2 个答案:

答案 0 :(得分:3)

看起来您的应用程序似乎需要单个顺序传递输入,因此处理1GB或100GB的文件可能只是耐心和平行的问题。

方法应该是逐行翻译记录。您应该避免尝试将整个文件读入内存的策略。 STL提供易于使用的std :: ifstream类,内置getline方法,返回包含要转换的行的std :: string。

如果您感觉更有野心,并且想要更仔细地控制读取或缓冲的数据量,那么您将不会成为第一个使用自己的代码来实现缓冲读取器的开发人员。这是一个相当有力的练习,将帮助您思考一些角落案例,阅读部分线条等。但最终,它可能不会为你的目标带来显着的推动。我怀疑ifstream方法可以帮助您顺利运行,而且不会成为处理这些文件的瓶颈。

如果您真的担心优化执行时间,那么拥有多个文件可能会帮助您启动并行处理任务。

// define a class to hold your custom record
class Record {
};

// create a parser function to convert a line of text into the record
bool parse(std::string const &line, Record &record) {
}

// create a translator method to convert a record into the desired output
bool write(Record const &record, std::ofstream &os) {
}

// actually open input stream for the input file
std::ifstream is;
std::ofstream os;
std::string line;

while (std::getline(is,line)) {
  Record record;
  if (!parse(line,record)) break;
  if (!write(record,os)) break;
}

只要您小心重置变量,以便前面记录中的信息不会污染当前记录,您可以通过将它移到while循环之外来重新使用Record实例。您还可以通过生成流输入和输出运算符(“&lt;&lt;”,“&gt;&gt;”)来首先进入C ++生态系统,但我个人认为这种方法比它的价值更加混乱。

答案 1 :(得分:1)

也许最好的方法是将CSV文件导入SQLite数据库。

导入并添加一些索引后,您可以轻松高效地从该数据库中查询必要的行。 SQLite提供了许多可立即使用的C / C ++客户端库,您可以从https://www.sqlite.org/cintro.html的默认值开始。