簡體   English   中英

緩慢的文件讀取和復制到內存-C ++

[英]Slow file reading and copying into memory - C++

我正在讀取文件並將數據保存到vector 我不能使用arrays因為數據大小不是固定的。 文件大小約為300kb,最大可達600kb。 目前,讀取/保存大約需要5-8秒。

我想知道是什么導致我的讀取/復制方法變慢,以及如何加以改進?

樣本數據:

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;

}

這似乎是預期的。 使用Boost::Progressctime隔離昂貴的指令。

向量是通過數組的方式在連續內存中實現的,因此,在那里您應該不會看到太多(如果有的話)減速。 對於600kb的文件,文件IO時間可能最短-我想它會在打開時緩存到內存中。 您可以使用file.open的ios::binary模式標志將整個文件緩存到內存中,但是您必須對每行進行反序列化-getline抽象的成本。

綜上所述,編譯器非常擅長優化IO和向量。 瓶頸可能是正則表達式(甚至正則表達式匹配)的構造,這是必要且復雜的。 每個正則表達式都會生成確定性有限狀態自動機: 平均正則表達式算法的時間復雜度是多少?

正則表達式功能強大,但復雜且緩慢。

由於您的格式是完全靜態的(固定的數字位數和中間的固定分隔符),因此您可以自己實現轉換,逐字符讀取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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM