【问题标题】:`fgetpos` Not Returning the Correct Position`fgetpos` 没有返回正确的位置
【发布时间】:2014-07-02 11:36:01
【问题描述】:

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

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 之后,我得到一个 58 的 position从 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);
}

编辑。根据 cmets 中的调试建议,我添加了以下代码

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

【问题讨论】:

  • 我认为“我创建的文件看起来像”和“几乎相同”之间有点缺失。也就是说,在 Windows 上,当您在文本模式下阅读时需要注意换行符转换,这可能是您的问题。
  • 谢谢你,我已经编辑了这个问题。文本文件是使用 C# 创建的,并使用默认编码 (Encoding.Default) 来编写文本文件。使用的行尾是\r\n,并且似乎对于有效的文件显示完全相同。我不知道为什么这个(我创建的文件)是 40 个中唯一一个无法使用上述代码返回正确位置的文件!?马车返回和换行符看起来不错!?
  • This question 可能是相关的(但不确定是否是骗局)。
  • 你可以尝试调用 fgetpos() 并立即调用 fsetpos() 和 ReadLine() 吗?如果这项工作必须在该职位之间的工作中。
  • 另外,使用 ftell() 调试

标签: c++ fgetpos


【解决方案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 错误?谁知道?这可能是未定义的行为。

fgets 失败时,最好不要依赖buffer 的值。

【讨论】:

  • 感谢您的宝贵时间。我将尝试这些更新并回复您……“无能”是我自己。我总共用 C/C++ 编码大约 4 周,所以很抱歉。
  • 尽管对我提供的代码进行了很好的重写,但这并没有解决错误fgetpos 结果的问题...
  • @Killercam:那肯定可以解释。你的能力会随着经验的增长而增长,尽管我想知道你从哪些资源中学到了导致这些错误的原因。我不确定是什么导致了奇怪的文件定位行为,如果不是代码中的未定义行为。使用调试器单步调试库代码可能是理解这一点的最直接途径。
  • Ben,为您的帮助喝彩,非常感谢您的时间。我只有一本基本的 C++ 书;我独自工作,孤立无援,因此不存在更高级人员的帮助。这就是为什么这个网站和像你这样的人对我如此有价值。明天我会考虑逐步浏览图书馆的东西,但我已经浪费了足够的时间并且有一个修复它的黑客 - 我可能会把它留在那里(危险)。再次感谢 - 一切顺利...
  • @Killercam:您可以查看 C++ 书籍的 SO 指南:stackoverflow.com/q/388242
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-26
相关资源
最近更新 更多