Обновление: чтобы обойти проблему ниже, я сделал
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);
Со всеми предоставленными мне файлами хранилище fgetpos
а также fsetpos
работает правильно. Проблема с файлом, который я создал, который выглядит как
который почти идентичен поставляемым файлам. Проблема в том, что для файла выше fgetpos(m_pFile, &position);
не возвращает правильный position
(Я знаю, что fpos_t position
является конкретной реализацией). После первого ReadLine
Я получаю position
из 58 (отредактировано от 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);
Извините, но ваши функции 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
достигает новой строки, заполняет буфер или достигает конца файла, вы гарантированно получите правильно завершенную строку в вашем буфере. Если возникает какая-то другая ошибка ввода / вывода? Кто знает? Это может быть неопределенное поведение.
Лучше не полагаться на ценность buffer
когда fgets
выходит из строя.