C-使用lseek移回文件中的指针

时间:2018-11-26 20:35:14

标签: c linux posix fcntl unistd.h

我正在用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);
  5. 将指针设置为当前位置

SEEK_SET-将指针设置为距文件开头的给定偏移量。在我的伪代码current_position中是偏移量。

实际上它可以正常工作,但是我总是将指针从文件的开头开始移动-我使用SEEK_SET-并没有进行优化。

lseek也接受参数SEEK_CUR-这是当前位置。如何将指针从指针(SEEK_CUR)的当前位置移回。我试图设置负偏移量,但是没有用。

2 个答案:

答案 0 :(得分:1)

从文件中读取数据行的最有效方法通常是读取可能跨越多行的大数据块,从该数据块中处理数据行直到到达末端,再从末端移出任何部分行从缓冲区开始,然后再读取另一块数据。根据目标系统和要执行的任务,可能最好读取足够的数据以填充分行后剩余的空间,或者始终读取二进制数的幂并增大缓冲区可能更好。足以容纳该大小的块以及最大长度的分行(上一读的内容遗留)。这种方法的一个困难是要使用同一缓冲区从流中读取所有数据。但是,在可行的情况下,与使用多个单独fread调用相比,它通常可以提供更好的性能,并且可能比使用fgets更好。

尽管标准库函数应该可以方便地进行行输入,但是fgets的设计是不必要的敌意,因为它无法方便地指示已读取多少数据。读取每一行之后,想要包含可打印部分的字符串的代码将必须使用strlen来尝试确定已读取了多少数据(希望输入不包含任何零字节),然后检查之前的字节尾随零以查看它是否为换行符。并非没有,但至少很尴尬。如果fread-and-buffer方法可以满足应用程序的需求,那么它可能至少与使用fgets一样有效(如果不是更多的话),并且由于健壮地使用fgets()所需的工作量是可比的达到使用缓冲方法所需要的缓冲,最好还是使用后者。

答案 1 :(得分:1)

由于您的问题被标记为,因此我会使用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