c - fseek/ftell 和 stat.st_size 在文本模式下不返回实际文件大小

标签 c

平台:windows
操作系统:XP sp3
编译器:gcc v4.8.1
文本编辑器:记事本
编码:ansi

问题:如何在文本模式下检索实际文件大小,以便我可以准确设置缓冲区大小?

    char *filename = "functions.txt";

    FILE *source = fopen(filename,"r");

    struct stat properites;

    stat(filename,&properties);

    long size_stat = properties.st_size;

    fseek(source,0,SEEK_END);
    long size_ftell = ftell(source);
    fseek(source,0,SEEK_SET);

    char *pchar_source = malloc(sizeof(char)*size_stat);

    long size_read = fread(pchar_source,sizeof(char),size_stat,source);


functions.txt
tokenize(字符串字符串,字符分隔符) String[] {

}

输出
文件大小统计 [70]
文件大小-ftell [70]
文件大小-fread [67]


对于小文件,差异可以忽略不计,但是,对于较大的文件,这意味着不必要的内存分配。有什么建议吗?


一种可能的解决方案:

long fileSize  = 0;

while (getc(source) != EOF)
{
    fileSize++;
}


但是,对于大文件来说,这非常浪费且耗时。

最佳答案

ftell为您提供正确的大小(以字节为单位)。正如其他人指出的那样,这是因为您有三个行结尾编码为 \r\n 。当您在 Windows 上以文本模式打开时,它们会转换为 \n ,因此您少读了三个字符。

我看到有两个选项:

  1. 使用ftell作为缓冲区大小的估计,但是,在 fread 之后,使用size_read在缓冲区大小的其余代码中。您只会浪费行数字节的内存,这不是什么大问题。

  2. 以二进制模式打开文件rb 。您将得到的尺寸为 70,而且还有 fread将返回 70 字节。然后编写代码时要理解行结尾可能是 \r , \n ,或\r\n .

从上面两个中,我真的推荐第二个选项:它提供了更强大和可移植的程序,并且二进制模式的概念比依赖于平台的文本模式更容易混淆。

关于c - fseek/ftell 和 stat.st_size 在文本模式下不返回实际文件大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24740172/

相关文章:

c - s [i]- '0'是什么意思?

c - 这些 typedef 用法有什么区别?

c - gethostbyname 的第二次调用给出段错误

c - 我不明白 strcmp 结果

c - c 中的美元找零程序

C没有开放函数

c - 使用 fwrite() 在 C 中逐字节写入文件

c - 如何求数组[N][M]的长度?

c - 这是C语言的思考。我不明白变量值是如何保留的

c++ - inotify 描述符上的读取被永远阻塞