0

更新:为了解决下面的问题,我已经完成了

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工作正常。问题在于我创建的文件看起来像

例如

这几乎与提供的文件相同。问题是上面的文件fgetpos(m_pFile, &position);没有返回正确的position(我知道这fpos_t position是特定于实现的)。在第一次之后,ReadLine我得到了position58 (从 60 编辑),所以当我尝试阅读第二行时

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);
4

1 回答 1

1

抱歉,您的 Utils 函数显然是由无能者编写的。有些问题只是风格问题。修剪:

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更糟糕的是,将其替换为:

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)让我特别担心。如果fgets到达换行符、填充缓冲区或到达文件末尾,则可以保证在缓冲区中获得正确终止的字符串。如果发生其他一些 I/O 错误?谁知道?这可能是未定义的行为。

最好不要依赖bufferwhenfgets失败的值。

于 2014-07-02T14:26:55.103 回答