平台: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
,因此您少读了三个字符。
我看到有两个选项:
使用
ftell
作为缓冲区大小的估计,但是,在fread
之后,使用size_read
在缓冲区大小的其余代码中。您只会浪费行数字节的内存,这不是什么大问题。以二进制模式打开文件
rb
。您将得到的尺寸为 70,而且还有fread
将返回 70 字节。然后编写代码时要理解行结尾可能是\r
,\n
,或\r\n
.
从上面两个中,我真的推荐第二个选项:它提供了更强大和可移植的程序,并且二进制模式的概念比依赖于平台的文本模式更容易混淆。
关于c - fseek/ftell 和 stat.st_size 在文本模式下不返回实际文件大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24740172/