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

时间:2016-03-24 17:03:47

标签: c++ arrays file vector

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

我想知道什么会减慢我的读/复制方法以及如何改进它?

示例数据:

  <00> 0000:4000 94 45 30 39 36 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;

}

2 个答案:

答案 0 :(得分:3)

这看起来像预期的那样。使用Boost::Progressctime隔离昂贵的说明。

向量是以数组的方式使用连续内存实现的,所以你不应该看到很多(如果有的话)减速。文件IO时间在600kb文件上可能是最小的 - 我想它在打开时缓存到内存中。您可以使用file.open的ios::binary模式标志将整个文件缓存到内存中,但是您必须反序列化每一行 - getline抽象的成本。

所有这一切,编译器非常擅长优化IO和向量。瓶颈可能是正则表达式的构建(甚至可能是正则表达式匹配),这是必要的&amp;复杂。为每个正则表达式生成确定性有限状态自动机:What's the Time Complexity of Average Regex algorithms?

答案 1 :(得分:2)

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

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

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

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