2013-05-08 30 views
0

我目前填補這樣一個類(這是相當緩慢的,我的目的)填充在一個匆忙的一類:C++從文件

void CBinLoader::LoadMatchesFromCompiledDat(clsMatches &uMatches) 
{ 
int size = 0; 
fread(&size,sizeof(int),1,m_infile); 

for(int i = 0; i < size; i++) 
{ 
    MatchNode newMatch; 
    newMatch.EnteredCharacter = ReadWStringFromCompiledDat(m_infile); 

    int PossibleResults_size = 0; 
    fread(&PossibleResults_size,sizeof(int),1,m_infile); 

    for(int j=0; j<PossibleResults_size; j++) 
    { 
     PossibleResult pr; 

     fread(&pr.LenToUseFromEnteredString, sizeof(int), 1, m_infile); 

     pr.Trans = ReadWStringFromCompiledDat(m_infile); 
     pr.NextChars = ReadWStringFromCompiledDat(m_infile); 
     pr.PrevTrans = ReadWStringFromCompiledDat(m_infile); 
     pr.PrevPrevTrans = ReadWStringFromCompiledDat(m_infile); 

     fread(&pr.SequenceID, sizeof(int), 1, m_infile); 

     newMatch.PossibleResults.push_back(pr); 
    }     

    uMatches.Content().push_back(newMatch); 

    } 
} 


wstring CBinLoader::ReadWStringFromCompiledDat(FILE *pFile) 
{ 
    //read the length of the string 
    int len = 0; 
    fread(&len, sizeof(int), 1, m_infile); 

    //make buffer with this length 
    wchar_t* pBuffer = NULL; 
    pBuffer = new wchar_t[len+1]; 
    memset(pBuffer, 0, (len+1)*sizeof(wchar_t)); 

    //read the string into the buffer 
    fread(pBuffer, sizeof(wchar_t), len, m_infile); 

    wstring result = pBuffer; 

    delete pBuffer; 
    return result; 
} 

是否有可能只是讀它在一個匆忙而不是一片一片地填充它?

+1

你如何確定慢度?花很長時間不同於緩慢。 – 2013-05-08 06:45:41

+0

這並不重要,但是你可以跳過動態分配並簡單地將你的'std :: wstring'調整爲先前讀取的大小,然後簡單地加載並返回它。不需要'new wchar_t []'也不需要後面的'delete [] pBuffer;'(你根本不用做,而是選擇'delete pBuffer';這本身就是一個bug)。 – WhozCraig 2013-05-08 06:53:49

+0

如果我能夠一口氣讀完它,它比填充它更快,就像我的方法一樣。 – tmighty 2013-05-08 06:54:04

回答

2

可以將POD的內存映像寫入文件,然後將其讀回(fread(pMyPod, sizeof(*pMyPod), 1, pFile);)。
但是,這非常有限:內存映像不是標準化的,所以在切換編譯器版本時它甚至可能會更改,並且在切換平臺時很有可能發生更改。
此外,更改類使文件無用。

序列化(到磁盤)時,有很多事情要考慮。我不認爲速度應該是一個主要問題。

0

可以提高ReadWStringFromCompiledDat方法,沒有內存分配和內存初始化:

wchar_t * pBuffer = NULL; 
pBuffer = new wchar_t[len+1]; 
memset(pBuffer, 0, (len+1)*sizeof(wchar_t)); 
fread(pBuffer, sizeof(wchar_t), len, m_infile); 

可以通過改變:

wchar_t pBuffer[len+1]; 
fread(pBuffer, sizeof(wchar_t), len, m_infile); 
pBuffer[len] = 0; 

有了這個新辦法,你不超載此方法記憶分配。

+0

我想'len'是一個非const變量,所以你建議不能編譯。 – 2013-05-08 07:04:35

+0

這使用了一個VLA,最後我檢查的是在C++中仍然不支持,至少通過C++ 11。 – WhozCraig 2013-05-08 07:05:06

0

理論上是的,但它需要一種完全不同的方式來構造數據,並且有可能讓代碼「依賴於平臺」。

讓我給你多一些「暗示」:

  • 雖然我們沒有關於ReadWString...是如何實現的想法,想想如何將字符串中寫道:如果他們可以具有可變長度,沒有方式使它成爲「一次衝刺」,因爲你必須知道一個字符串何時結束,然後才能閱讀下一個。

  • 如果你可以將所有數據讀/寫在一個靜態定義的非多態性數據結構一樣

    struct { /* only plain types and statically sized arrays here */; };

可以FREAD/FWRITE整個支柱(不管如果你希望你的數據可以被不同類型的機器讀取,那麼你應該注意結構體成員對齊方式(即編譯器和平臺相關)。

但在提供「隨機優化」之前,嘗試在啓用所有優化的情況下對其進行編譯後對代碼進行概要分析。有多少「緩慢」是由於處理和IO等待的原因造成的?

如果問題是I/O,您可以讀取行緩衝區中的整個文件,然後處理緩衝區中的數據。如果問題正在處理,那麼您必須重新考慮數據的表示方式以及數據結構的存儲方式。

+0

非常感謝! – tmighty 2013-05-08 07:20:17