Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用C++; 我的目标是在OSX环境下,在QT项目中用C++解析大型CSV文件。 (当我说csv时,我指的是tsv和其他1GB~5GB的变体)_C++_Qt_Csv_Large Files - Fatal编程技术网

使用C++; 我的目标是在OSX环境下,在QT项目中用C++解析大型CSV文件。 (当我说csv时,我指的是tsv和其他1GB~5GB的变体)

使用C++; 我的目标是在OSX环境下,在QT项目中用C++解析大型CSV文件。 (当我说csv时,我指的是tsv和其他1GB~5GB的变体),c++,qt,csv,large-files,C++,Qt,Csv,Large Files,这似乎是一项简单的任务,但当文件大小变大时,事情会变得复杂。我不想编写自己的解析器,因为有许多与解析csv文件相关的边缘情况 我已经找到了各种csv处理库来处理这项工作,但在我的机器上解析1GB文件大约需要90~120秒,这是不可接受的。我现在没有对数据做任何事情,我只是为了测试目的处理和丢弃数据 是我尝试过的图书馆之一。但唯一足够快的库是,它给出了可接受的结果:在我的机器上15秒,但它只有在已知文件结构时才能工作 示例使用: #包括“csv.h” int main(){ io::CSVRead

这似乎是一项简单的任务,但当文件大小变大时,事情会变得复杂。我不想编写自己的解析器,因为有许多与解析csv文件相关的边缘情况

我已经找到了各种csv处理库来处理这项工作,但在我的机器上解析1GB文件大约需要90~120秒,这是不可接受的。我现在没有对数据做任何事情,我只是为了测试目的处理和丢弃数据

是我尝试过的图书馆之一。但唯一足够快的库是,它给出了可接受的结果:在我的机器上15秒,但它只有在已知文件结构时才能工作

示例使用:

#包括“csv.h”
int main(){
io::CSVReader in(“ram.csv”);
在.read_标题中(io::忽略额外_列,“供应商”、“大小”、“速度”);
字符串供应商;整数大小;双速度;
while(在行中(供应商、尺寸、速度)){
//处理数据
}
}
正如您所看到的,我不能加载任意文件,我必须专门定义变量以匹配我的文件结构。我不知道有任何方法允许我在运行时动态创建这些变量

我尝试过的另一种方法是使用LineReader类逐行读取csv文件,这非常快(读取整个文件大约需要7秒),然后使用可以处理字符串的lib解析每一行,但这需要大约40秒,与第一次尝试相比,这是一种改进,但仍然无法接受

我见过各种与csv文件解析相关的堆栈溢出问题,其中没有一个需要考虑大文件处理

我还花了很多时间在谷歌上寻找这个问题的解决方案,我真的很怀念像npmpip这样的包经理在搜索现成解决方案时所提供的自由

对于如何处理这个问题,我将不胜感激

编辑:

使用的方法时,处理时间减少到25秒,这是一个很大的改进


我们可以进一步优化它吗?

我假设您只使用一个线程

多线程可以加快进程

到目前为止,最好的成绩是40秒。让我们坚持下去

我假设您先阅读,然后处理->(大约7秒读取整个文件)

7秒阅读 33秒用于处理

首先您可以将文件分成块,比如50MB。 这意味着您可以在读取50MB文件后开始处理。您不需要等到整个文件完成。 读取时间为0.35秒(现在处理时间为0.35+33秒=cca 34秒)

使用多线程时,可以一次处理多个块。从理论上讲,这可以加速这个过程,达到你们的核心数。假设你有4个核。 这是33/4=8.25秒

我认为您可以使用4个内核加快处理速度,总共9秒。

看和或 我更喜欢游泳池

将任务分为几个部分:

  • 首先,尝试循环文件并将其分成块。什么都不要做
  • 然后创建可以处理该块的“ChunkProcessor”类
  • 使“ChunkProcessor”成为重新实现的run()函数的子类,并在其中执行进程
  • 当您有块时,您有可以处理它们的类,并且该类与QThreadPool兼容,您可以将其传递到
  • 它可能看起来像这样

    loopoverfile {
      whenever chunk is ready {
         ChunkProcessor *chunkprocessor = new ChunkProcessor(chunk);
         QThreadPool::globalInstance()->start(chunkprocessor);
         connect(chunkprocessor, SIGNAL(finished(std::shared_ptr<ProcessedData>)), this, SLOT(readingFinished(std::shared_ptr<ProcessedData>)));
      }   
    }
    
    或者你可以使用主要的想法:(我不知道为什么阅读需要7秒,它背后是什么)

    QFile文件(“in.txt”);
    如果(!file.open(QIODevice::ReadOnly | QIODevice::Text))
    返回;
    QByteArray*数据=新的QByteArray;
    整数计数=0;
    而(!file.atEnd()){
    ++计数;
    数据->附加(file.readLine());
    如果(计数>10000){
    ChunkProcessor*ChunkProcessor=新的ChunkProcessor(数据);
    QThreadPool::globalInstance()->启动(chunkprocessor);
    连接(chunkprocessor,SIGNAL(finished(std::shared_ptr)),此,插槽(readingFinished(std::shared_ptr));
    数据=新的QByteArray;
    计数=0;
    }
    }
    
    一个文件,一个线程,读取速度几乎和“无”中断地逐行读取一样快。 处理数据是另一个问题,但与I/O无关。它已经在内存中。 因此,唯一需要考虑的是机器上的5GB文件和RAM容量


    这是一个非常简单的解决方案,所有您需要的是子类QRunnable、重新实现run函数、完成时发出信号、使用共享指针传递处理后的数据,并在主线程中将该数据连接到一个结构或其他任何结构中。简单的线程安全解决方案。

    我会提出一个多线程的建议,但有一点不同,即一个线程专用于读取预定义(可配置)大小的数据块,并不断将数据提供给一组线程(基于多个cpu核)。假设配置如下所示:

    块大小=50MB
    磁盘线程=1
    进程线程数=5

  • 创建用于从文件中读取数据的类。在这个类中,它拥有一个用于与进程线程通信的数据结构。例如,此结构将包含每个进程线程的读取缓冲区的起始偏移量、结束偏移量。对于读取文件数据,reader类拥有两个块大小的缓冲区(在本例中为50MB)
  • 创建一个进程类,该类保存读取缓冲区和偏移量数据结构的指针(共享)
  • 现在创建驱动程序(可能是主线程),创建所有线程并等待它们完成,并处理信号
  • 读卡器线程是用re调用的
    loopoverfile {
      whenever chunk is ready {
         ChunkProcessor *chunkprocessor = new ChunkProcessor(chunk);
         QThreadPool::globalInstance()->start(chunkprocessor);
         connect(chunkprocessor, SIGNAL(finished(std::shared_ptr<ProcessedData>)), this, SLOT(readingFinished(std::shared_ptr<ProcessedData>)));
      }   
    }
    
    qRegisterMetaType<std::shared_ptr<ProcessedData>>("std::shared_ptr<ProcessedData>");
    
    QByteArray data = file.readAll();
    
     QFile file("in.txt");
     if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
       return;
    
     QByteArray* data = new QByteArray;    
     int count = 0;
     while (!file.atEnd()) {
       ++count;
       data->append(file.readLine());
       if ( count > 10000 ) {
         ChunkProcessor *chunkprocessor = new ChunkProcessor(data);
         QThreadPool::globalInstance()->start(chunkprocessor);
         connect(chunkprocessor, SIGNAL(finished(std::shared_ptr<ProcessedData>)), this, SLOT(readingFinished(std::shared_ptr<ProcessedData>)));
         data = new QByteArray; 
         count = 0;
       }
     }