2014-07-02 102 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:那肯定会解释它。你的能力会随着经验的增长而增长,但我不知道你从中学到了哪些资源导致了这些错误。我不确定是什么导致了怪异的文件定位行为,如果在代码中没有未定义的行为。可能通过调试器来浏览库代码是理解该问题的最直接途径。 –