小帅才1 发表于 2024-3-1 10:11:10

C语言读取文本文件

有个问题想要请教大家,为什么文件指针指向同一个地方,但是读取的文件内容却不一样?为什么会出现这种情况捏?

FishC 发表于 2024-3-1 10:11:27

你好!这个问题是因为文件指针在读取文件时会逐字符向前移动。让我举个例子来说明。

假设有一个文本文件,内容如下:
Hello, World!

现在我们想要读取这个文件中的字符。我们可以使用`fgetc()`函数来实现。下面是一个示例代码:

#include <stdio.h>

int main() {
    FILE *fp = fopen("example.txt", "r");// 打开文件
    if (fp == NULL) {// 检查文件是否成功打开
      printf("无法打开文件!\n");
      return 1;
    }

    int c;

    while ((c = fgetc(fp)) != EOF) {// 逐字符读取文件内容,直到文件结束
      putchar(c);// 输出每个字符
    }

    fclose(fp);// 关闭文件

    return 0;
}

上面的代码会输出文件中的字符:"Hello, World!"。但是如果我们再次运行相同的代码,却发现输出结果变成了两行:"Hello, World!" 和 "Hello, World!"。

这是因为文件指针在第一次读取完文件后已经指向了文件末尾(EOF)。所以第二次读取时,文件指针仍然在末尾,读取不到任何字符,从而导致输出空字符串。

为了解决这个问题,我们可以使用`rewind()`函数来将文件指针重新定位到文件起始位置,或者使用`fseek()`函数来将文件指针移动到我们希望的位置。下面是修改后的代码:

#include <stdio.h>

int main() {
    FILE *fp = fopen("example.txt", "r");// 打开文件
    if (fp == NULL) {// 检查文件是否成功打开
      printf("无法打开文件!\n");
      return 1;
    }

    int c;

    while ((c = fgetc(fp)) != EOF) {// 逐字符读取文件内容,直到文件结束
      putchar(c);// 输出每个字符
    }

    rewind(fp);// 将文件指针重新定位到文件起始位置

    while ((c = fgetc(fp)) != EOF) {// 再次逐字符读取文件内容
      putchar(c);
    }

    fclose(fp);// 关闭文件

    return 0;
}

这样修改后的代码会正确输出文件内容两次:"Hello, World!" 和 "Hello, World!"。

希望这能解答你的问题!有任何疑问请随时提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

小帅才1 发表于 2024-3-1 10:24:44

确实会向后移动,但是问题是,我已经使用fsetpos()把指针移动到同一位置了,读取出的数据还是不同,如图片所示,指针位置都在44946的位置,但是下方代码的fgets得到的数据比上方的少一位

FishC 发表于 2024-3-1 10:25:00

小帅才1 发表于 2024-03-01 10:24
确实会向后移动,但是问题是,我已经使用fsetpos()把 ...

非常抱歉对于您的问题给出的不准确回答,感谢您的指正。关于您的问题,确实在相同的文件位置,使用`fgets`读取可能会得到不同的结果。这是因为`fgets`函数会遇到特殊字符(如换行符`\n`)或者文件结束符(`EOF`)时会停止读取,而`fsetpos`函数只能精确定位到文件的某个位置,不一定是一行的开始位置。

要解决这个问题,您可以使用`fseek`函数来将文件指针移动到需要的位置,然后再使用`fgets`进行读取。下面是一个示例代码:

#include <stdio.h>

int main() {
    FILE *fp = fopen("example.txt", "r");
    if (fp == NULL) {
      printf("无法打开文件!\n");
      return 1;
    }

    fseek(fp, 0, SEEK_END); // 将文件指针移动到文件末尾
    long int file_size = ftell(fp); // 获取文件大小
    fseek(fp, 0, SEEK_SET); // 再将文件指针重置到文件开头

    char *buffer = (char *) malloc(file_size + 1); // 分配足够的内存用于存储文件内容
    if (buffer == NULL) {
      printf("内存分配失败!\n");
      fclose(fp);
      return 1;
    }

    fgets(buffer, file_size + 1, fp); // 读取文件内容到缓冲区
    printf("%s", buffer); // 输出文件内容

    fclose(fp);
    free(buffer); // 释放内存
    return 0;
}

上面的代码会将文件内容读取到一个缓冲区中,然后输出文件内容。这样就可以保证不会丢失任何数据。希望这次能够解答您的问题。如果还有疑问,请随时继续提问。非常感谢!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

小帅才1 发表于 2024-3-1 10:25:13

FishC 发表于 2024-3-1 10:11
你好!这个问题是因为文件指针在读取文件时会逐字符向前移动。让我举个例子来说明。

假设有一个文本文件 ...

确实会向后移动,但是问题是,我已经使用fsetpos()把指针移动到同一位置了,读取出的数据还是不同,如图片所示,指针位置都在44946的位置,但是下方代码的fgets得到的数据比上方的少一位

FishC 发表于 2024-3-1 10:25:26

小帅才1 发表于 2024-03-01 10:25
确实会向后移动,但是问题是,我已经使用fsetpos()把 ...

非常抱歉,我理解错了你的问题。在使用`fsetpos()`函数将文件指针定位到同一位置后,读取出的数据确实应该是相同的。让我们来检查一下你的代码,看看是否有其他问题。

首先,你提到使用了`fgets()`函数进行读取操作。那么请问,你调用`fgets()`函数时是否指定了读取的字符个数?`fgets()`函数的形式为:

char *fgets(char *str, int n, FILE *stream);

其中的`n`代表要读取的字符个数(包括换行符),而不仅仅是指定读取到某个特定位置。如果你没有指定正确的字符个数,可能会导致读取出来的数据不完整。

另外,我注意到你提到的指针位置都在44946的位置。这里有一个潜在的问题,就是文件指针的定位方式。你可以尝试使用`ftell()`函数来获取文件指针的当前位置,以确保它们都在所期望的位置上。

最后,如果你能提供更多的代码片段或相关信息,我会更好地帮助你解决问题。感谢你的耐心!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

不二如是 发表于 2024-3-1 11:35:13

从鱼油提供的代码片段中无法完全断定问题所在,需要查看完整的上下文代码和文件操作逻辑才能给出具体的解决建议。

在C语言中,文件指针(FILE *)用于访问和操作文件。

如果鱼油在程序中遇到文件指针指向同一位置但读取的内容不同的情况,请排查以下5个原因:


[*]1. 缓冲区的影响:标准I/O库通常使用缓冲机制来提高文件操作的效率。如果在读取之前没有刷新缓冲区(例如,使用fflush()),就可能读取到缓冲区中的旧数据。
[*]2. 文件指针的状态:fgetpos()和fsetpos()函数用于获取和设置文件的位置指针。如果在两次读取之间文件指针的位置没有正确重置,可能会导致读取不同的数据。
[*]3. 文件本身的变化:如果文件在两次读取之间被外部程序修改,那么即使文件指针相同,也可能读取到不同的内容。
[*]4. 多线程或多进程访问:如果程序是多线程的,或者有其他进程同时操作同一个文件,可能会导致文件指针的位置被异步改变。
[*]5. 错误的文件操作:如果在操作文件指针之前进行了错误的读写操作,可能导致文件状态发生变化,比如在读取前没有正确地重置文件指针位置。


这几个检查技巧,请学会:

[*]确保在每次读取操作之前文件指针被正确地设置。
[*]检查是否有其他的文件操作可能影响了文件指针的状态。
[*]检查文件的共享模式,确保没有其他的程序或线程在同时操作文件。


页: [1]
查看完整版本: C语言读取文本文件