Как прочитать 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
→ Ссылка