Рубрики

Реализуйте свой собственный хвост (прочитайте последние n строк огромного файла)

Учитывая огромный файл с динамическими данными, напишите программу для чтения последних n строк из файла в любой точке без чтения всего файла. Проблема похожа на команду tail в linux, которая отображает последние несколько строк файла. В основном он используется для просмотра обновлений файла журнала, поскольку эти обновления добавляются в файлы журнала.

Источник: Microsoft Интервью

Мы настоятельно рекомендуем вам свернуть браузер и попробовать это в первую очередь.

Проблема в основном сосредоточена на следующих вещах —

1. Программа не должна читать весь файл.
2. Программа должна обрабатывать входящие динамические данные и возвращать последние n строк в любой точке.
3. Программа не должна закрывать входной поток перед чтением последних n строк.

Ниже его реализация C ++

// C ++ программа для реализации собственного хвоста
#include <bits/stdc++.h>

using namespace std;

  
#define SIZE 100

  
// Служебная функция для сна в течение n секунд

void sleep(unsigned int n)

{

    clock_t goal = n * 1000 + clock();

    while (goal > clock());

}

  
// функция для чтения последних n строк из файла
// в любой момент без чтения всего файла

void tail(FILE* in, int n)

{

    int count = 0;  // Для подсчета символов '/ n'

  

    // unsigned long long pos (сохраняет до 2 ^ 64 - 1

    // chars) при условии, что long long int занимает 8

    // байты

    unsigned long long pos;

    char str[2*SIZE];

  

    // Перейти к концу файла

    if (fseek(in, 0, SEEK_END))

        perror("fseek() failed");

    else

    {

        // pos не будет содержать символов в

        // входной файл.

        pos = ftell(in);

  

        // поиск символов '/ n'

        while (pos)

        {

            // Переместить 'pos' от конца файла.

            if (!fseek(in, --pos, SEEK_SET))

            {

                if (fgetc(in) == '\n')

  

                    // прекращаем чтение, когда n новых строк

                    // находится

                    if (count++ == n)

                        break;

            }

            else

                perror("fseek() failed");

        }

  

        // выводим последние n строк

        printf("Printing last %d lines -\n", n);

        while (fgets(str, sizeof(str), in))

            printf("%s", str);

    }

    printf("\n\n");

}

  
// Создает файл, печатает и вызывает tail () для
// 10 разных значений n (от 1 до 10)

int main()

{

    FILE* fp;

    char buffer[SIZE];

    // Открыть файл в двоичном режиме

    // режим wb + для чтения и записи одновременно

    fp = fopen("input.txt", "wb+");

    if (fp == NULL)

    {

        printf("Error while opening file");

        exit(EXIT_FAILURE);

    }

    srand(time(NULL));

  

    // Динамически добавлять строки во входной файл

    // и каждый раз вызываем tail ()

    for (int index = 1; index <= 10; index++)

    {

        / * генерировать случайные журналы для печати во входном файле * /

        for (int i = 0; i < SIZE - 1; i++)

            buffer[i] = rand() % 26 + 65; // AZ

        buffer[SIZE] = '\0';

  

        / * код для печати отметки времени в журналах * /

        // получаем текущее календарное время

        time_t ltime = time(NULL);

  

        // asctime () возвращает указатель на строку

        // который представляет день и время

        char* date = asctime(localtime(&ltime));

  

        // заменить символ '/ n' в строке даты

        // с '/ 0' для печати в той же строке.

        date[strlen(date)-1] = '\0';

  

        / * Примечание в текстовом режиме '/ n' добавляет два символа,

        поэтому мы открыли файл в двоичном режиме * /

        fprintf(fp, "\nLine #%d [%s] - %s", index,

                                    date, buffer);

  

        // очистить поток ввода перед вызовом tail

        fflush(fp);

  

        // читаем последние строки индекса из файла

        tail(fp, index);

  

        // спать 3 секунды

        // отметить разницу в метках времени в логах

        sleep(3);

    }

  

    / * закрыть файл перед завершением программы * /

    fclose(fp);

  

    return 0;

}

Некоторые моменты, на которые стоит обратить внимание —
1. Этот код не будет работать на онлайн-компиляторе, так как требует разрешения на создание файла. При запуске на локальном компьютере он создает пример входного файла «input.txt», динамически записывает в него данные 10 раз и каждый раз вызывает функцию tail ().

2. Мы должны избегать использования fseek () и ftell () для больших файлов (в ГБ), так как они работают с позициями файлов типа long int. Вместо этого используйте _fseeki64 (), _ftelli64 ().

3. unsigned long имеет максимально допустимое значение 2 32 — 1 (при условии, что unsigned long занимает 4 байта). Может использоваться для файлов размером менее 4 ГБ.

4. unsigned long long имеет максимально допустимое значение 2 64 — 1 (при условии, что unsigned long long занимает 8 байтов). Может использоваться для файлов размером более 4 ГБ.

Эта статья предоставлена Aditya Goel . Пожалуйста, напишите комментарии, если вы обнаружите что-то неправильное, или вы хотите поделиться дополнительной информацией по обсуждаемой теме

Рекомендуемые посты:

Реализуйте свой собственный хвост (прочитайте последние n строк огромного файла)

0.00 (0%) 0 votes