C - перемещение указателя в файле с помощью lseek - PullRequest
0 голосов
/ 26 ноября 2018

Я пишу академический проект на C и могу использовать только библиотеки <fcntl.h> и <unistd.h> для файловых операций.

У меня есть функция для чтения файла строка за строкой.Алгоритм:

  1. Установить указатель на начало файла и получить текущую позицию.
  2. Считать данные в буфер (char buf[100]) с постоянным размером, итерация символ за символоми определить конец строки '\n'.
  3. Увеличить текущую позицию: curr_pos = curr_pos + length_of_read_line;
  4. Установить указатель на текущую позицию, используя lseek(fd, current_position, SEEK_SET);

SEEK_SET -установить указатель на заданное смещение от начала файла.В моем псевдокоде current_position - это смещение.

И на самом деле все работает нормально, но я всегда перемещаю указатель, начиная с начала файла - я использую SEEK_SET - он не оптимизирован.

lseek принять также аргумент SEEK_CUR - это текущая позиция.Как я могу переместить указатель назад из текущей позиции указателя (SEEK_CUR).Я пытался установить отрицательное смещение, но не сработало.

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

Поскольку ваш вопрос помечен как , я бы выбрал getline(), без необходимости вручную перемещать указатель файла.

Пример:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    FILE* fp;
    char* line = NULL;
    size_t len = 0;
    ssize_t read;

    fp = fopen("input.txt", "r");
    if(fp == NULL)
        return -1;

    while((read = getline(&line, &len, fp)) != -1) 
    {
        printf("Read line of length %zu:\n", read);
        printf("%s", line);
    }

    fclose(fp);
    if(line)
        free(line);
    return 0;
}

Вывод с пользовательским вводом:

Read line of length 11:
first line
Read line of length 12:
second line
Read line of length 11:
third line
0 голосов
/ 26 ноября 2018

Наиболее эффективный способ чтения строк данных из файла - это обычно чтение большого фрагмента данных, который может занимать несколько строк, обработка строк данных из фрагмента до тех пор, пока один из них не достигнет конца, перемещение любой частичной строки с концабуфера в начало, а затем прочитать другой кусок данных.В зависимости от целевой системы и задачи, которая должна быть выполнена, может быть лучше прочитать достаточно, чтобы заполнить оставшееся пространство после неполной строки, или может быть лучше всегда читать число байтов со степенью двух и сделать буфер большимдостаточно для размещения фрагмента такого размера плюс частичная строка максимальной длины (оставшаяся от предыдущего чтения).Единственная сложность этого подхода заключается в том, что все данные для чтения из потока используют один и тот же буфер.Однако в тех случаях, когда это целесообразно, он часто обеспечивает лучшую производительность, чем использование множества отдельных вызовов на fread, и может быть лучше, чем использование fgets.

Хотя это должно быть возможно для стандартныхФункция библиотеки, облегчающая ввод строки, дизайн fgets довольно ненужно враждебна, поскольку не дает удобного указания на то, сколько данных она прочитала.После прочтения каждой строки код, который хочет получить строку, содержащую печатаемую часть, должен будет использовать strlen, чтобы попытаться выяснить, сколько данных было прочитано (возможно, входные данные не будут содержать нулевых байтов), а затем проверить байт перед завершающимноль, чтобы увидеть, если это новая строка.Не невозможно, но по крайней мере неловко.Если подход с использованием алгоритма Fread-and-Buffer удовлетворит потребности приложения, он, вероятно, будет по меньшей мере столь же эффективным, как использование fgets, если не более, и поскольку усилия, необходимые для надежного использования fgets(), будут сопоставимы с теми, которые требуются дляиспользуйте подход буферизации, также можно использовать последний.

...