Как прочитать input.txt в обратном порядке строк
файл input.txt
1 2
3 4
5 6
7 8
9 10
11 12
Мне надо его прочитать в обратно порядке строк.
11 12
9 10
7 8
5 6
3 4
1 2
Именно прочитать, потому как это упрощенная версия файла, в то время как настоящий будет очень большим, так что читать его несколько раз не желательно, как и записывать его целиком. Под прочитать я имею ввиду записать в переменную на время каждое число, также для идентификации знать текущую строчку. Я пробовал, но дальше указателя к файлу я не смог продвинутся
Ответы (1 шт):
Автор решения: Pak Uula
→ Ссылка
Вот вариант с предварительным индексирование концов строк
#include <iostream> // std::cout
#include <fstream> // std::ifstream
#include <vector> // массив концов строк
#include <cstring> // memchr
#include <chrono> // отсечки времени
#include <string> // для вывода буфера `char*`
// Читать мегабайт за раз
const size_t BUF_SIZE = 1024 * 1024;
const char *strnchr(const char *buf, char ch, size_t num)
{
return static_cast<const char *>(memchr(buf, ch, num));
}
int main()
{
std::vector<size_t> newlines{0};
char buf[BUF_SIZE];
size_t buf_start{0};
std::ifstream is("/mnt/hdd/nikolay/some.txt", std::ifstream::binary); // 10Гб
// std::ifstream is("some.txt", std::ifstream::binary); // 1 Гб
// std::ifstream is("main.cpp", std::ifstream::binary); // маленький файл
// Индексирование переводов строк
is.seekg(0, is.beg);
{
auto start = std::chrono::high_resolution_clock::now();
while (is)
{
auto len = is.readsome(buf, BUF_SIZE);
if (len <= 0)
{
break;
}
auto end = buf + len;
for (const char *ptr = strnchr(buf, '\n', end - buf); ptr != NULL; ptr = strnchr(ptr + 1, '\n', end - ptr))
{
newlines.push_back(buf_start + (ptr - buf));
}
buf_start += len;
}
auto elapsed = std::chrono::high_resolution_clock::now() - start;
long long milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(
elapsed)
.count();
std::cerr << "Время индексирования концов строк: " << milliseconds << "ms" << std::endl;
std::cerr << "Число строк: " << newlines.size() << std::endl;
}
// Чтение строк
{
auto start = std::chrono::high_resolution_clock::now();
is.seekg(0, is.end);
size_t end = is.tellg();
for (auto start = newlines.crbegin(); start != newlines.crend() && end > 0; start++)
{
is.seekg(*start);
// Чтение строки. За раз читается не более 1 Мб
for (size_t len = end - *start; len > 0;)
{
size_t size = (len < BUF_SIZE) ? len : BUF_SIZE;
len -= size;
is.readsome(buf, size);
std::cout << std::string(buf, size);
}
end = *start;
}
auto elapsed = std::chrono::high_resolution_clock::now() - start;
long long milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(
elapsed)
.count();
std::cerr << "Время чтения и вывода строк в обратном порядке: " << milliseconds << "ms" << std::endl;
}
is.close();
return 0;
}
Вывод программы для 10Гб файла:
Время индексирования концов строк: 447ms
Число строк: 8388482
Время чтения и вывода строк в обратном порядке: 5383ms