Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.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+中快速读取文本文件+; 我目前正在编写一个C++程序,其中包括阅读大量的文本文件。每行约有400.000行,在极端情况下,每行包含4000个或更多字符。为了进行测试,我使用ifstream和cplusplus.com提供的实现读取了其中一个文件。这花了大约60秒,太长了。现在我想知道,有没有一种简单的方法可以提高阅读速度_C++_Performance_Io_Ifstream - Fatal编程技术网

在c+中快速读取文本文件+; 我目前正在编写一个C++程序,其中包括阅读大量的文本文件。每行约有400.000行,在极端情况下,每行包含4000个或更多字符。为了进行测试,我使用ifstream和cplusplus.com提供的实现读取了其中一个文件。这花了大约60秒,太长了。现在我想知道,有没有一种简单的方法可以提高阅读速度

在c+中快速读取文本文件+; 我目前正在编写一个C++程序,其中包括阅读大量的文本文件。每行约有400.000行,在极端情况下,每行包含4000个或更多字符。为了进行测试,我使用ifstream和cplusplus.com提供的实现读取了其中一个文件。这花了大约60秒,太长了。现在我想知道,有没有一种简单的方法可以提高阅读速度,c++,performance,io,ifstream,C++,Performance,Io,Ifstream,编辑: 我使用的代码大致如下: string tmpString; ifstream txtFile(path); if(txtFile.is_open()) { while(txtFile.good()) { m_numLines++; getline(txtFile, tmpString); } txtFile.close(); } 编辑2:我读取的文件只有82 MB大。我主要是说它可以达到4000,因为我认为可能需要知道才能

编辑: 我使用的代码大致如下:

string tmpString;
ifstream txtFile(path);
if(txtFile.is_open())
{
    while(txtFile.good())
    {
        m_numLines++;
        getline(txtFile, tmpString);
    }
    txtFile.close();
}
编辑2:我读取的文件只有82 MB大。我主要是说它可以达到4000,因为我认为可能需要知道才能进行缓冲

编辑3:谢谢大家的回答,但鉴于我的问题,似乎没有太多的改进空间。我必须使用readline,因为我想计算行数。将ifstream实例化为二进制文件也不会加快读取速度。我将尽可能多地将其并行化,这至少应该是可行的


编辑4:显然有些事情我可以做。非常感谢sehe在这方面投入了这么多时间,我非常感谢!=)

更新:确保检查初始答案下方的(令人惊讶的)更新


内存映射文件对我很有用1:


更新 通过查看GNU coreutils
wc
的源代码,我发现我可以从中挤出最后一点性能。令我惊讶的是,使用从
wc
改编的以下(大大简化)代码运行的时间约占上述内存映射文件运行时间的84%

static uintmax_t wc(char const *fname)
{
    static const auto BUFFER_SIZE = 16*1024;
    int fd = open(fname, O_RDONLY);
    if(fd == -1)
        handle_error("open");

    /* Advise the kernel of our access pattern.  */
    posix_fadvise(fd, 0, 0, 1);  // FDADVICE_SEQUENTIAL

    char buf[BUFFER_SIZE + 1];
    uintmax_t lines = 0;

    while(size_t bytes_read = read(fd, buf, BUFFER_SIZE))
    {
        if(bytes_read == (size_t)-1)
            handle_error("read failed");
        if (!bytes_read)
            break;

        for(char *p = buf; (p = (char*) memchr(p, '\n', (buf + bytes_read) - p)); ++p)
            ++lines;
    }

    return lines;
}


1请参见此处的基准测试:

4000*400000=1.6 GB如果硬盘驱动器不是SSD,则可能会获得约100 MB/s的顺序读取。仅在I/O中就需要16秒

由于您没有详细说明您使用的特定代码或您需要如何解析这些文件(您需要逐行读取它吗,系统是否有大量RAM?您可以将整个文件读入一个大的RAM缓冲区,然后解析它吗?),因此您几乎无法加快该过程

按顺序读取文件时,内存映射文件不会提供任何性能改进。也许手动解析大块新行而不是使用“getline”可以提供改进

学习后编辑(谢谢@sehe)。下面是我可能会使用的内存映射解决方案

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <errno.h>

int main() {
    char* fName = "big.txt";
    //
    struct stat sb;
    long cntr = 0;
    int fd, lineLen;
    char *data;
    char *line;
    // map the file
    fd = open(fName, O_RDONLY);
    fstat(fd, &sb);
    //// int pageSize;
    //// pageSize = getpagesize();
    //// data = mmap((caddr_t)0, pageSize, PROT_READ, MAP_PRIVATE, fd, pageSize);
    data = mmap((caddr_t)0, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    line = data;
    // get lines
    while(cntr < sb.st_size) {
        lineLen = 0;
        line = data;
        // find the next line
        while(*data != '\n' && cntr < sb.st_size) {
            data++;
            cntr++;
            lineLen++;
        }
        /***** PROCESS LINE *****/
        // ... processLine(line, lineLen);
    }
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main(){
char*fName=“big.txt”;
//
结构统计某人;
长cntr=0;
int fd,lineLen;
字符*数据;
字符*行;
//映射文件
fd=打开(仅fName,Ordu);
财政司司长(财务司司长及财务司司长);
////int页面大小;
////pageSize=getpagesize();
////数据=mmap((caddr t)0,页面大小,保护读取,映射私有,fd,页面大小);
数据=mmap((caddr t)0,标准尺寸,保护读取,地图私有,fd,0);
行=数据;
//排队
而(cntr
使用
随机文件访问
或使用
二进制模式
。对于sequential,这是一个很大的问题,但仍然取决于您正在阅读的内容。

您必须同时读取所有文件吗?(例如,在应用程序开始时)

如果您这样做,请考虑并行化操作。


无论哪种方式,考虑使用二进制流,或unbffffd用于数据块。

< P>作为一个在竞争编程中有点背景的人,我可以告诉你:至少对于像整数解析这样简单的事情,C中的主要开销是锁定文件流(默认情况下是多线程处理)。改用
unlocked_stdio
版本(
fgetc_unlocked()
fread_unlocked()
)。对于C++,一般的知识是使用<代码> STD::IOS:SycSyOffStdio(false)< /C> >但我不知道它是否和<代码> unLokKdStdio一样快。 这里是我的标准整数解析代码供参考。它比scanf快得多,正如我所说的,主要是因为没有锁定流。对我来说,它和我以前使用的最好的手工编码mmap或自定义缓冲版本一样快,没有疯狂的维护债务

int readint(void)
{
        int n, c;
        n = getchar_unlocked() - '0';
        while ((c = getchar_unlocked()) > ' ')
                n = 10*n + c-'0';
        return n;
}
(注意:只有当任意两个整数之间正好有一个非数字字符时,此项才有效)


当然,如果可能的话,请避免内存分配…

尼尔·柯克,很遗憾,我无法回复您的评论(声誉不够),但我对ifstream和stringstream进行了性能测试,逐行读取文本文件的性能完全相同

std::stringstream stream;
std::string line;
while(std::getline(stream, line)) {
}
对于一个106MB的文件,这需要1426ms

std::ifstream stream;
std::string line;
while(ifstream.good()) {
    getline(stream, line);
}
在同一个文件上需要1433毫秒

以下代码速度更快:

const int MAX_LENGTH = 524288;
char* line = new char[MAX_LENGTH];
while (iStream.getline(line, MAX_LENGTH) && strlen(line) > 0) {
}
在同一个文件上需要884ms。
这只是有点棘手,因为您必须设置缓冲区的最大大小(即输入文件中每行的最大长度)。

使用随机归档还是顺序归档?向我们展示您的代码或您正在阅读的内容?这在很大程度上取决于您在使用它时所做的操作。您可能希望将其拆分为多个部分,因为这对我来说似乎是一个内存瓶颈400000行*4000个特许权可能是160000000个字符,如果您的系统问题中一个字符是1字节,则可能是字节,您在实际代码中使用过stringstreams吗?它们的速度很慢。只需检查..+1的啤酒杯垫计算。不过SSD的速度可以达到约500Gb/s。内存映射可能更有效,这取决于使用场景。我需要逐行读取内存映射,因为它们不包含告诉我它们有多长的头。我可以把它们放在RAM缓冲区中,因为我可以在读取它们之后丢弃它们,但再一次,我认为ifstream就是这么做的。有没有办法告诉公关
std::ifstream stream;
std::string line;
while(ifstream.good()) {
    getline(stream, line);
}
const int MAX_LENGTH = 524288;
char* line = new char[MAX_LENGTH];
while (iStream.getline(line, MAX_LENGTH) && strlen(line) > 0) {
}