Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.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++_Arrays_File_Vector - Fatal编程技术网

慢速文件读取和复制到内存C++

慢速文件读取和复制到内存C++,c++,arrays,file,vector,C++,Arrays,File,Vector,我正在读取一个文件并将数据保存到一个向量中。我无法使用数组,因为数据大小不固定。文件大小约为300kb,最高可达600kb。目前,读取/保存大约需要5-8秒 我想知道是什么使我的读取/复制方法变慢,以及如何改进 样本数据: 0000:4000 94 45 30 39 36 39 74 00 00 50 00 00 27一些 其他信息在这里 这似乎是意料之中的事。使用Boost::Progress或ctime隔离昂贵的指令 向量是以数组的方式使用连续内存实现的,因此如果有任何减速,您应该不会看到太

我正在读取一个文件并将数据保存到一个向量中。我无法使用数组,因为数据大小不固定。文件大小约为300kb,最高可达600kb。目前,读取/保存大约需要5-8秒

我想知道是什么使我的读取/复制方法变慢,以及如何改进

样本数据:

0000:4000 94 45 30 39 36 39 74 00 00 50 00 00 27一些 其他信息在这里


这似乎是意料之中的事。使用Boost::Progress或ctime隔离昂贵的指令

向量是以数组的方式使用连续内存实现的,因此如果有任何减速,您应该不会看到太多。在600kb的文件上,文件IO时间可能是最小的——我可以想象它是在打开时缓存到内存中的。您可以使用file.open的ios::binary mode标志将整个文件缓存到内存中,但您必须反序列化每一行,以减少getline抽象的开销


综上所述,编译器非常擅长优化IO和向量。瓶颈可能是正则表达式的构造,甚至可能是正则表达式匹配的构造,这些都是必要且复杂的。每个正则表达式都会生成一个确定性有限状态自动机:。

这似乎是意料之中的。使用Boost::Progress或ctime隔离昂贵的指令

向量是以数组的方式使用连续内存实现的,因此如果有任何减速,您应该不会看到太多。在600kb的文件上,文件IO时间可能是最小的——我可以想象它是在打开时缓存到内存中的。您可以使用file.open的ios::binary mode标志将整个文件缓存到内存中,但您必须反序列化每一行,以减少getline抽象的开销


综上所述,编译器非常擅长优化IO和向量。瓶颈可能是正则表达式的构造,甚至可能是正则表达式匹配的构造,这些都是必要且复杂的。每个正则表达式都会生成一个确定性有限状态自动机:。

正则表达式非常强大,但复杂且缓慢

由于您的格式是完全静态的固定位数和固定分隔符,您可以自己实现转换,逐字符读取。这不会很复杂

例如,要读取所有十六进制数并检查空格和分号:

while(getline(file,str))
{
    if(str.size()>=57)
    {
        int sector = hexToInt(str.data(), 4);
        int address = hexToInt(str.data()+5, 4);

        bool ok = ok && (sector==0) && (address>=0);

        ok = ok && str[4] == ':';

        int bytes[16];
        for(int i=0;i<16;++i)
        {
            bytes[i] = hexToInt(str.data()+10+3*i, 2);
            ok = ok && (str[9+3*i]==' ') && (bytes[i]>=0);
        }
    }

    //Etc...
}
用于检查和转换十六进制数字的功能:

int hexCharToDigit(char c)
{
    if(c>='0' && c<='9')
    {
        //Decimal digit
        return (int)(c-'0');
    }
    else if (str[i]>='a' && str[i]<='f')
    {
        //Hexadecimal lower case letter
        return (int)(c-'a')+10;
    }
    else if (str[i]>='A' && str[i]<='F')
    {
        //Hexadecimal upper case letter
        return (int)(c-'A')+10;
    }
    else
    {
        //Char is not a hex digit
        return -1;
    }  
}
用于检查n位十六进制并将其转换为整数的函数:

int hexToInt(const char * chr, int size)
{
    assert(size<8);

    int result= 0;
    for(int i=0;i<size;++i)
    {
        int hexDigit = hexCharToDigit(chr[i]);
        if(hexDigit>=0)
        {
            //Valid hexadecimal digit
            result = result << 4;
            result += hexDigit;
        }
        else
        {
            //Char is not a hex digit as expected
            return -1;
        }   
    }

    return result;
}

正则表达式非常强大,但复杂且缓慢

由于您的格式是完全静态的固定位数和固定分隔符,您可以自己实现转换,逐字符读取。这不会很复杂

例如,要读取所有十六进制数并检查空格和分号:

while(getline(file,str))
{
    if(str.size()>=57)
    {
        int sector = hexToInt(str.data(), 4);
        int address = hexToInt(str.data()+5, 4);

        bool ok = ok && (sector==0) && (address>=0);

        ok = ok && str[4] == ':';

        int bytes[16];
        for(int i=0;i<16;++i)
        {
            bytes[i] = hexToInt(str.data()+10+3*i, 2);
            ok = ok && (str[9+3*i]==' ') && (bytes[i]>=0);
        }
    }

    //Etc...
}
用于检查和转换十六进制数字的功能:

int hexCharToDigit(char c)
{
    if(c>='0' && c<='9')
    {
        //Decimal digit
        return (int)(c-'0');
    }
    else if (str[i]>='a' && str[i]<='f')
    {
        //Hexadecimal lower case letter
        return (int)(c-'a')+10;
    }
    else if (str[i]>='A' && str[i]<='F')
    {
        //Hexadecimal upper case letter
        return (int)(c-'A')+10;
    }
    else
    {
        //Char is not a hex digit
        return -1;
    }  
}
用于检查n位十六进制并将其转换为整数的函数:

int hexToInt(const char * chr, int size)
{
    assert(size<8);

    int result= 0;
    for(int i=0;i<size;++i)
    {
        int hexDigit = hexCharToDigit(chr[i]);
        if(hexDigit>=0)
        {
            //Valid hexadecimal digit
            result = result << 4;
            result += hexDigit;
        }
        else
        {
            //Char is not a hex digit as expected
            return -1;
        }   
    }

    return result;
}

最有可能是正则表达式破坏了您的性能:最好在计算if运算符时在第一位设置更简单的语句,以防&&我不知道firstAddress==-1的频率,但如果不是,它将不会运行正则表达式搜索…数据格式很简单。不要使用正则表达式。另外,您应该估计数据的大小并避免重新分配:使用vector::reserve。尝试使用一些中值大小声明向量。您可能会看到由于重新分配std::vector而造成的时间浪费。我建议450kb。@ZDF,向量重新分配不是这里的瓶颈。vector在最后提供了摊销常数时间的插入。最有可能的是正则表达式破坏了您的性能:最好在第一位设置更简单的语句来计算if运算符,以防&&我不知道firstAddress==-1的频率,但如果不是,它就不会运行正则表达式搜索…数据格式很简单。不要使用正则表达式。另外,您应该估计数据的大小并避免重新分配:使用vector::reserve。尝试使用一些中值大小声明向量。您可能会看到由于重新分配std::vector而造成的时间浪费。我建议450kb。@ZDF,向量重新分配不是这里的瓶颈。vector提供了在最后以摊销的固定时间进行插入的功能。速度慢也可能是由于std::vector重新分配内存造成的。@ThomasMatthews,可能性极低。在完成一些基准测试后,正则表达式搜索是原因。因为我知道每行中的数据位置,所以我将手动提取它。谢谢你的帮助。速度慢也可能是由于std::vector重新分配内存造成的。@ThomasMatthews,可能性极小。在做了一些基准测试之后,正则表达式搜索是原因。因为我知道每行中的数据位置,所以我将手动提取它。谢谢你的帮助。在做了一些基准测试之后,正则表达式搜索就是原因。因为我知道每行中的数据位置,所以我将手动提取它。谢谢你抽出时间。如果需要的话,我可以使用你的一些函数。在做了一些基准测试之后,正则表达式搜索就是原因。因为我知道数据 在每一行中,我将手动提取它。谢谢你抽出时间。如果需要,我可以使用你的一些功能。