Есть несколько условий, которые необходимо учитывать при резервном копировании поиска последней строки в текстовом файле.
- Вам не важно, какой последний символ в файле. Файл может иметь (или не иметь) POSIX конец файла (
'\n'
в качестве последнего символа последней строки), - , что имеет значение при поиске конец файла, вы тоже не в начале (empty-file); тогда вы можете
- начать цикл, просматривая
'\n'
перед последней строкой в файле (сохранить счетчик смещения от конца и, когда смещение не равно единице до конца, и file.peek() == '\n'
, затем прервите цикл и, наконец, - проверьте, что вы не в начале или если 1 st char равен
'\n'
, если так, продвиньте позицию файла на единицу, и - прочитайте последнюю строку.
Вы можете закодировать логи c несколькими различными способами, но если вы делаете это в функции, вы либо передадите ссылку на открыть std::ifstream
или передать имя файла для открытия в функции. Если вы передаете ссылку на открытый файловый поток, вы хотите, чтобы тип возвращаемой функции был такой же ссылкой на открытый файловый поток, что поток состояние может быть проверено для обнаружения ошибки потока (вы также проверите string.length() != 0
при возврате, чтобы убедиться, что файл не был пустым)
В целом, вы можете написать файл get last line используя ваши файловые операции simi Lar to:
#include <iostream>
#include <fstream>
#include <string>
std::ifstream& getlastline (std::ifstream& f, std::string& last)
{
long offsetend = 0; /* initial offset from end */
/* if file not empty */
if (f.seekg(offsetend, std::ios_base::end) && f.tellg())
/* loop continually seeking 1 before current offsetend */
while (f.seekg(offsetend - 1, std::ios_base::end)) {
/* if at beginning or offsetend and '\n' */
if (!f.tellg() || (offsetend < 0 && f.peek() == '\n'))
break;
offsetend--; /* decrement offsetend */
}
/* if not at beginning, or 1st char is '\n' advance by 1 */
if (f.tellg() || f.peek() == '\n')
f.seekg(offsetend, std::ios_base::end);
if (!getline (f, last)) /* read last line */
std::cerr << "error: getline() read of last line.\n";
return f; /* return stream state */
}
Добавляя короткий пример, который позволяет вам указать имя файла для чтения в качестве первого аргумента программы, вы можете сделать:
int main (int argc, char **argv) {
if (argc < 2) {
std::cerr << "error: filename required as 1st argument.\n";
return 1;
}
std::string last {};
std::ifstream f (argv[1]);
if (!getlastline (f, last) || last.length() == 0) {
std::cerr << "error: stream error or file was empty.\n";
return 1;
}
std::cout << last << '\n';
}
Подойдя к нему так: Кстати, вы получите последнюю строку независимо от того, есть ли в файле конец файла POSIX, и он также будет обрабатывать случай пустого файла.
Конечно, если все файлы, с которыми вы имеете дело, имеют несколько сотен строк или меньше, вы можете полностью отказаться от смещения от конца и просто прочитать все строки, сохранив последние - это создает драматизм c упрощение, например
#include <iostream>
#include <fstream>
#include <string>
int main (int argc, char **argv) {
if (argc < 2) {
std::cerr << "error: filename required as 1st argument.\n";
return 1;
}
std::string current {}, last {};
std::ifstream f (argv[1]);
while (getline (f, current))
last = current;
/* (add any length validations here) */
std::cout << last << '\n';
}
Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.