Implemente su propia cola (lea las últimas n líneas de un archivo enorme)

Dado un archivo enorme con datos dinámicos, escriba un programa para leer las últimas n líneas del archivo en cualquier punto sin leer todo el archivo. El problema es similar al comando tail en Linux, que muestra las últimas líneas de un archivo. Se utiliza principalmente para ver actualizaciones de archivos de registro, ya que estas actualizaciones se agregan a los archivos de registro.

Fuente: entrevista de Microsoft

Le recomendamos encarecidamente que minimice su navegador y que pruebe esto usted mismo primero.

El problema se centra principalmente en las cosas siguientes:

1. El programa no debe leer el archivo completo.
2. El programa debe manejar los datos dinámicos entrantes y devolver las últimas n líneas en cualquier punto.
3. El programa no debe cerrar el flujo de entrada antes de leer las últimas n líneas.

A continuación se muestra su implementación en 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 '\n' 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 '\n' characters
        while (pos)
        {
            // Move 'pos' away from end of file.
            if (!fseek(in, --pos, SEEK_SET))
            {
                if (fgetc(in) == '\n')
  
                    // 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", n);
        while (fgets(str, sizeof(str), in))
            printf("%s", str);
    }
    printf("\n\n");
}
  
// 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; // A-Z
        buffer[SIZE] = '\0';
  
        /* 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 '\n' character in the date string
        // with '\0' to print on the same line.
        date[strlen(date)-1] = '\0';
  
        /* Note in text mode '\n' appends two characters,
        so we have opened file in binary mode */
        fprintf(fp, "\nLine #%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;
}

Algunos puntos para la Nota:
1. Este código no funcionará en el compilador en línea, ya que requiere permisos de creación de archivos. Cuando se ejecuta la máquina local, produce un archivo de entrada de muestra «input.txt» y escribe datos dinámicamente en él 10 veces y llama a la función tail() cada vez.

2. Deberíamos evitar usar fseek() y ftell() para archivos grandes (en GB) ya que operan en posiciones de archivo de tipo long int. Utilice _fseeki64(), _ftelli64() en su lugar.

3. unsigned long tiene un valor máximo permitido de 2 32 – 1 (suponiendo que unsigned long toma 4 bytes). Se puede utilizar para archivos de menos de 4 GB de tamaño.

4. unsigned long long tiene un valor máximo permitido de 2 64 – 1 (suponiendo que unsigned long long toma 8 bytes). Se puede utilizar para archivos de más de 4 GB.

Este artículo es una contribución de Aditya Goel . Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *