平台:windows
o / s: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 string,Character delimiter)String []
{
}
输出
file size-stat [70]
file size-ftell [70]
文件大小 - 恐惧[67]
对于小文件,差异可以忽略不计,但是,对于文件较大的文件,这意味着不必要的内存分配。有什么建议吗?
一种可能的解决方案:
long fileSize = 0;
while (getc(source) != EOF)
{
fileSize++;
}
但是,对于大型文件来说,这是非常浪费和耗时的。
答案 0 :(得分:3)
ftell
为您提供正确的字节大小。正如其他人所说,这是因为你有三个行结尾编码为\r\n
。当您在Windows上以文本模式打开时,它们会转换为\n
,因此您可以阅读三个字符。
我看到两个选项:
使用ftell
作为缓冲区大小的估计值,但是在fread
之后,在代码的其余部分中使用size_read
作为缓冲区大小。你只会浪费行数字节的内存,这不是什么大问题。
以二进制模式rb
打开文件。您将获得70的大小,但fread
将返回70个字节。然后编写代码,理解行结尾可能是\r
,\n
或\r\n
。
从上面两个我真的推荐第二个选项:它提供了一个更强大和可移植的程序,二进制模式的概念比平台相关的文本模式更少混淆。
答案 1 :(得分:1)
如果"尺寸"该文件将以依赖于文件内容的单位给出,然后准确地确定该大小需要扫描整个文件。
这正是在Windows上以文本模式打开的任何文件的情况(因为物理" \ r \ n"被视为单个逻辑单元)。如果文件内容以某种方式编码,并且您想要解码单元的数量也是如此。这听起来不太可能,因为它经常出现字符编码,例如编码为UTF-8字节流的(21位)Unicode字符。
至于创建一个缓冲区来保存整个文件内容,
realloc()
(例如,当需要时)阅读文件)。答案 2 :(得分:-2)
<强>答案:强> 不,你不能。
实际文件大小,而不是&#34;估计&#34;,仅在完整阅读后才可用。这是由于新行和编码类型的转换(如果有)。对于那些想知道,这里是&#34;适当的&#34;确定实际文件大小的方法。
char *filename = "sample.txt";
FILE *file_source = fopen(filename,"r"); // can be set to either "r" or "rb"
// use stat.st_size if you have the library <sys/stat.h>
struct stat stat_sourceFile;
stat(filename,&stat_sourceFile);
long long_fileSize_stat = stat_sourceFile.st_size; // estimate only
// use fseek,ftell,fseek if you dont have the lib <sys/stat.h>
fseek(file_source,0,SEEK_END);
long long_fileSize_ftell = ftell(file_source); // estimate only
fseek(file_source,0,SEEK_SET);
char *pchar_source = malloc(sizeof(char)*long_fileSize_stat);
long long_ACTUAL_FILE_SIZE = fread(pchar_source,sizeof(char),long_fileSize_stat,file_source);
realloc(pchar_source,long_ACTUAL_FILE_SIZE);
// now when we pass the pointer/array size to ANY function/method, you WONT
// get those funny characters not part of your file at the end of your
// printf statements. also, instead of using long_ACTUAL_FILE_SIZE as
// the bounds for iteration, you could use strlen(pchar_source)
希望这可以帮助其他新手进行c和文件缓冲。