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

Опубликовано: 1 Января, 2022

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

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

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

Проблема в основном сосредоточена на вещах ниже -

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

Ниже представлена его реализация на C ++.

// C++ program to implement your own tail
#include <bits/stdc++.h>
using namespace std;
#define SIZE 100
// Utility function to sleep for n seconds
void sleep(unsigned int n)
{
clock_t goal = n * 1000 + clock ();
while (goal > clock ());
}
// function to read last n lines from the file
// at any point without reading the entire file
void tail( FILE * in, int n)
{
int count = 0; // To count ' ' characters
// unsigned long long pos (stores upto 2^64 – 1
// chars) assuming that long long int takes 8
// bytes
unsigned long long pos;
char str[2*SIZE];
// Go to End of file
if ( fseek (in, 0, SEEK_END))
perror ( "fseek() failed" );
else
{
// pos will contain no. of chars in
// input file.
pos = ftell (in);
// search for ' ' characters
while (pos)
{
// Move 'pos' away from end of file.
if (! fseek (in, --pos, SEEK_SET))
{
if ( fgetc (in) == ' ' )
// stop reading when n newlines
// is found
if (count++ == n)
break ;
}
else
perror ( "fseek() failed" );
}
// print last n lines
printf ( "Printing last %d lines - " , n);
while ( fgets (str, sizeof (str), in))
printf ( "%s" , str);
}
printf ( " " );
}
// Creates a file and prints and calls tail() for
// 10 different values of n (from 1 to 10)
int main()
{
FILE * fp;
char buffer[SIZE];
// Open file in binary mode
// wb+ mode for reading and writing simultaneously
fp = fopen ( "input.txt" , "wb+" );
if (fp == NULL)
{
printf ( "Error while opening file" );
exit (EXIT_FAILURE);
}
srand ( time (NULL));
// Dynamically add lines to input file
// and call tail() each time
for ( int index = 1; index <= 10; index++)
{
/* generate random logs to print in input file*/
for ( int i = 0; i < SIZE - 1; i++)
buffer[i] = rand () % 26 + 65; // AZ
buffer[SIZE] = '' ;
/* code to print timestamp in logs */
// get current calendar time
time_t ltime = time (NULL);
// asctime() returns a pointer to a string
// which represents the day and time
char * date = asctime ( localtime (<ime));
// replace the ' ' character in the date string
// with '' to print on the same line.
date[ strlen (date)-1] = '' ;
/* Note in text mode ' ' appends two characters,
so we have opened file in binary mode */
fprintf (fp, " Line #%d [%s] - %s" , index,
date, buffer);
// flush the input stream before calling tail
fflush (fp);
// read last index lines from the file
tail(fp, index);
// sleep for 3 seconds
// note difference in timestamps in logs
sleep(3);
}
/* close the file before ending program */
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 ГБ.

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

Хотите узнать о лучших видео и практических задачах, ознакомьтесь с базовым курсом C ++ для базового и продвинутого уровня C ++ и курсом C ++ STL для базового уровня плюс STL. Чтобы завершить подготовку от изучения языка к DS Algo и многому другому, см. Полный курс подготовки к собеседованию .
C++ C