缓慢的文件读取和复制到内存-C++

Slow file reading and copying into memory - C++

本文关键字:内存 -C++ 复制 文件 读取 缓慢      更新时间:2023-10-16

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

我想知道是什么减缓了我的阅读/复制方法,以及如何改进它?

样本数据:

0000:4000 94 45 30 39 39 74 00 00 00 00 50 00 00 00 27部分其他信息在这里

int SomeClass::Open () 
{
    vector <unsigned int> memory; // where the data will be stored
    file.open("c:\file.txt",ios::in);
    regex addressPattern("0000:(\d|[a-z]){4}"); // used to extract the address from a string
    regex dataPattern("( (\d|[a-z]){2}){16}"); // used to extract the data from a string
    smatch match;
    string str; // where each line will be stored
    string data; // where the data found in each line will be stored
    int firstAddress = -1; // -1 = address not been found
    unsigned int sector = 0;
    unsigned int address = 0;
    while(getline(file,str)){
         if(regex_search(str,match,addressPattern) && firstAddress == -1){ 
             sector = std::stoul(match.str().substr(0,3),nullptr,16);
             address = std::stoul(match.str().substr(5),nullptr,16);
             firstAddress = address;
         }
         if(regex_search(str,match,dataPattern)){
            std::istringstream stream(str);
            string data; // used to store individual byte from dataString
            while(stream >> data){
                unsigned int c = std::stoul(data,nullptr,16); // convertion from hex to dec
                memory.insert(memory.end(),c);
            }
         }
    }
    return 0;
}

这似乎是意料之中的事。使用Boost::Progressctime来隔离代价高昂的指令。

矢量是以数组的方式用连续内存实现的,所以您不应该看到太多(如果有的话)速度减慢。对于600kb的文件来说,文件IO时间可能是最短的——我想它在打开时会缓存到内存中。您可以使用file.open的ios::binary模式标志将整个文件缓存到内存中,但您必须反序列化每一行——这是getline抽象的代价。

尽管如此,编译器在优化IO和向量方面做得非常好。瓶颈可能是正则表达式的构造(甚至正则表达式匹配),这是必要的&复杂的为每个正则表达式生成确定性有限状态自动机:What';平均Regex算法的时间复杂性是什么?。

Regex的功能非常强大,但复杂而缓慢。

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

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

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的函数:

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;
}