【问题标题】:C - moving back the pointer in the file using lseekC - 使用 lseek 移回文件中的指针
【发布时间】:2019-04-28 13:01:37
【问题描述】:

我正在用 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)向后移动指针。我尝试设置负偏移,但没有成功。

【问题讨论】:

  • 为什么要寻找?如果读取文件的一部分,文件指针指向下一个要读取的位置。
  • 请编辑您的帖子并将您的完整代码包含在代码块中。如果没有它,我们无法判断您的错误可能是什么。
  • 是的,但是我已经读取了 100 个字节,并且行尾可能位于 65 位。读完每一行后,我必须将指针设置为文件的开头。
  • ... 但没有用。 这不是一个有用的问题描述。一点也不。发布一个完整的代码示例,演示您的问题、您认为错误的地方以及您认为应该做的事情。
  • SEEK_SET 有什么问题?

标签: c linux posix fcntl unistd.h


【解决方案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

【讨论】:

    【解决方案2】:

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

    虽然标准库函数应该可以促进行输入,但fgets 的设计是不必要的敌对,因为它不能方便地指示它读取了多少数据。读取每一行后,需要包含可打印部分的字符串的代码必须使用strlen 来尝试确定读取了多少数据(希望输入不会包含任何零字节),然后检查尾随之前的字节零以查看它是否是换行符。不是不可能,但至少很尴尬。如果 fread-and-buffer 方法将满足应用程序的需求,它可能至少与使用 fgets 一样有效,如果不是更多的话,并且因为稳健使用 fgets() 所需的努力将与使用 fgets() 所需的努力相当使用缓冲方法,也可以使用后者。

    【讨论】:

    • getline() 是 POSIX,所以鉴于 posix 标签我会在这里推荐它。
    猜你喜欢
    • 1970-01-01
    • 2018-03-14
    • 1970-01-01
    • 2021-11-06
    • 1970-01-01
    • 1970-01-01
    • 2014-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多