2014-07-02 97 views
0

更新:要解決以下問題,我已經做了`fgetpos`不返回正確的位置

if (ftell(m_pFile) != m_strLine.size()) 
    fseek(m_pFile, m_strLine.size(), SEEK_SET); 
fpos_t position; 
fgetpos(m_pFile, &position); 

這則返回我的文件的正確位置。但是,我仍然想明白爲什麼會發生這種情況?


我想獲得文本文件中的位置。對於大多數的文件,我一直在讀的第一線,存儲位置,做一些其他的東西,迴歸後的位置...

m_pFile = Utils::OpenFile(m_strBaseDir + "\\" + Source + "\\" + m_strFile, "r"); 
m_strLine = Utils::ReadLine(m_pFile); 
bEOF = feof(m_pFile) != 0; 
if (bEOF) 
{ 
    Utils::CompilerError(m_ErrorCallback, 
     (boost::format("File '%1%' is empty.") % m_strFile).str()); 
    return false; 
} 

// Open. 
pFileCode = Utils::OpenFile(strGenCode + "\\" + m_strFile, options.c_str()); 
m_strLine = Utils::Trim(m_strLine); 
Utils::WriteLine(pFileCode, m_strLine); 

// Store location and start passes. 
unsigned int nLineCount = 1; 
fpos_t position; 
fgetpos(m_pFile, &position); 
m_strLine = Utils::ReadLine(m_pFile); 
... 
fsetpos(m_pFile, &position); 
m_strLine = Utils::ReadLine(m_pFile); 

隨着我提供正確fgetposfsetpos作品的存儲所有文件。問題是,我已經創建了一個文件,它看起來像

EG

這幾乎等同於提供的文件。問題是對於fgetpos(m_pFile, &position);以上的文件沒有返回正確的position(我知道fpos_t position是特定於實現的)。第一ReadLine後,我得到一個position 58(編輯),所以,當我試圖與

fsetpos(m_pFile, &position); 
m_strLine = Utils::ReadLine(m_pFile); 

讀第二行,我得到

在700

而不是

選擇函數ADJEXCL

爲什麼fgetpos不返回第一行結尾的位置?


_注意。該Utils.ReadLine方法是:

std::string Utils::ReadLine(FILE* file) 
{ 
    if (file == NULL) 
     return NULL; 
    char buffer[MAX_READLINE]; 
    if (fgets(buffer, MAX_READLINE, file) != NULL) 
    { 
     if (buffer != NULL) 
     { 
     std::string str(buffer); 
     Utils::TrimNewLineChar(str); 
     return str; 
     } 
    } 
    std::string str(buffer); 
    str.clear(); 
    return str; 
} 

void Utils::TrimNewLineChar(std::string& s) 
{ 
    if (!s.empty() && s[s.length() - 1] == '\n') 
     s.erase(s.length() - 1); 
} 

編輯。繼在評論中調試建議我加入以下代碼

m_pFile = Utils::OpenFile(m_strBaseDir + "\\" + Source + "\\" + m_strFile, "r"); 
m_strLine = Utils::ReadLine(m_pFile); 
// Here m-strLine = "   Logic Definition Report Chart Version: New Version 700" (64 chars). 
long vv = ftell(m_pFile); // Here vv = 58!? 

fpos_t pos; 
vv = ftell(m_pFile); 
fgetpos(m_pFile, &pos); // pos = 58. 
fsetpos(m_pFile, &pos); 
m_strLine = Utils::ReadLine(m_pFile); 
+0

我認爲在「我創建的文件看上去像」和「幾乎相同」之間有一點缺失。也就是說,在Windows上,當你在文本模式下閱讀時,你需要小心換行符,這可能是你的問題。 – molbdnilo

+0

謝謝你,我編輯了這個問題。該文本文件是用C#創建的,並使用默認編碼('Encoding.Default')來編寫文本文件。使用的行結尾是'\ r \ n',並且對於可以工作的文件似乎顯示完全相同。我失去了爲什麼這個(我創建的文件)是40箇中唯一一個無法使用上面的代碼返回正確位置的!回報和換行符看起來不錯!? – MoonKnight

+0

[這個問題](http://stackoverflow.com/q/15649089/2065121)可能是相關的(不知道它是否是一個愚蠢的)。 –

回答

1

很抱歉,但你的utils的功能已經明確寫了由一個不稱職的。有些問題只是一個風格問題。修剪:

std::string Utils::ReadLine(FILE* file) 
{ 
    std::string str; 
    char buffer[MAX_READLINE]; 
    if (file != NULL && fgets(buffer, MAX_READLINE, file) != NULL) 
    { 
     // it is guaranteed that buffer != NULL, since it is an automatic array 
     str.assign(buffer); 
     Utils::TrimNewLineChar(str); 
    } 
    // copying buffer into str is useless here 
    return str; 
} 

,在原來的後顧之憂最後str(buffer)我特別:

void Utils::TrimNewLineChar(std::string& s) 
{ 
    if (!s.empty() && *s.rbegin() == '\n') 
     s.resize(s.size() - 1); // resize, not erase 
} 

或C++ 11

void Utils::TrimNewLineChar(std::string& s) 
{ 
    if (!s.empty() && s.back() == '\n') 
     s.pop_back(); 
} 

ReadLine更是雪上加霜,將其替換爲。如果fgets到達換行符,填充緩衝區或達到文件結尾,則保證在緩衝區中獲得正確終止的字符串。如果發生其他一些I/O錯誤?誰知道?這可能是未定義的行爲。

fgets失敗時,最好不要依賴buffer的值。

+0

謝謝你的時間將嘗試這些更新並回復給你...'無能'是我自己。我一直在C/C++中編寫了大約4周的時間,非常抱歉。 – MoonKnight

+0

儘管對我提供的代碼進行了很好的重寫,但這並沒有幫助錯誤的'fgetpos'結果的問題... – MoonKnight

+0

@ Killercam:那肯定會解釋它。你的能力會隨着經驗的增長而增長,但我不知道你從中學到了哪些資源導致了這些錯誤。我不確定是什麼導致了怪異的文件定位行爲,如果在代碼中沒有未定義的行爲。可能通過調試器來瀏覽庫代碼是理解該問題的最直接途徑。 –