如何确定文件的大小,以字节为单位?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
stat
获取路径的信息或fstat
获取已打开文件描述符的信息(参见POSIX手册页,Linux手册页)。
(通过open(2)
获取文件描述符,或者在stdio流中使用fileno(FILE*)
)。基于NilObject的代码:#include <sys/stat.h>
#include <sys/types.h>
off_t fsize(const char *filename) {
struct stat st;
if (stat(filename, &st) == 0)
return st.st_size;
return -1;
}
变更:
const char
。struct stat
的定义,该定义缺少变量名。-1
而不是0
,对于空文件来说使用0
会有歧义。由于off_t
是有符号类型,因此这是可能的。如果您想使fsize()
在出现错误时打印一条消息,可以使用以下内容:
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
off_t fsize(const char *filename) {
struct stat st;
if (stat(filename, &st) == 0)
return st.st_size;
fprintf(stderr, "Cannot determine size of %s: %s\n",
filename, strerror(errno));
return -1;
}
在32位系统中,您应该使用选项-D_FILE_OFFSET_BITS=64
编译此内容,否则off_t
只能容纳最多2 GB的值。有关详细信息,请参阅Linux中的大文件支持中的“使用LFS”部分。
fseek
+ ftell
。 - Ciro Santilli OurBigBook.comfseek
和ftell
。不行。C标准明确规定,在二进制文件上使用fseek()
到SEEK_END
是未定义的行为。 7.19.9.2 fseek
函数 ...二进制流可能不支持具有SEEK_END
值的whence参数的fseek
调用,正如下面所注释的,这是链接C标准的第267页上脚注234中所述,并且明确将在二进制流中的fseek
到SEEK_END
标记为未定义的行为。 - Andrew Henle不要使用 int
。现在2GB以上的文件很常见。
不要使用 unsigned int
。现在4GB以上的文件也很普遍。
据我所知,标准库将 off_t
定义为无符号64位整数,这就是每个人都应该使用的类型。当我们开始处理16 exabyte文件时,我们可以在未来几年内重新定义它为128位。
如果您在Windows上,则应使用GetFileSizeEx - 它实际上使用了有符号的64位整数,因此他们会在处理8 exabyte文件时遇到问题。愚蠢的微软! :-)
马特的解决方案应该有效,除了它是C++而不是C,并且初始的tell应该不是必要的。
unsigned long fsize(char* file)
{
FILE * f = fopen(file, "r");
fseek(f, 0, SEEK_END);
unsigned long len = (unsigned long)ftell(f);
fclose(f);
return len;
}
我为你修复了括号, ;)
更新:这并不是最佳解决方案。在Windows上仅限于4GB文件,并且使用类似GetFileSizeEx
或stat64
的特定于平台的调用可能比它更慢。
ftell()
返回long int
。(unsigned long)
强制转换无法扩展范围,因为其已经被该函数限制。ftell()
在出错时返回-1,并且使用强制转换会使错误更加难以理解。建议fsize()
返回与ftell()
相同的类型。 - chux - Reinstate Monicaint
,即使在 long
是 64 位类型的 64 位系统上,它也无法处理大文件。(例如,大多数非 Windows 64 位系统使用 LP64 ABI)。但实际上,您应该使用返回 off_t
的 ftello
,在每个支持大文件的系统上都是 64 位的。 - Peter Cordes不要这样做(为什么?):
引用我在网上找到的C99标准文档:“将文件位置指示器设置为文件结尾,如使用
fseek(file,0,SEEK_END)
,对于二进制流(由于可能存在尾随的空字符)或具有状态相关编码但保证不以初始移位状态结束的任何流来说,都具有未定义的行为。”
更改定义为int,以便错误消息可以传递,然后使用fseek()
和ftell()
来确定文件大小。
int fsize(char* file) {
int size;
FILE* fh;
fh = fopen(file, "rb"); //binary mode
if(fh != NULL){
if( fseek(fh, 0, SEEK_END) ){
fclose(fh);
return -1;
}
size = ftell(fh);
fclose(fh);
return size;
}
return -1; //error
}
fseeko
和ftello
(或者如果你没有前一种方式并且可以接受对能够处理的文件大小设置限制,可以使用fseek
和ftell
)是正确的方法。基于stat
的解决方案不能在许多“文件”(例如块设备)上工作,并且不能移植到非类POSIX系统。 - R.. GitHub STOP HELPING ICEint
。ftell
返回一个带符号的 long
,在许多(但不是所有)64位系统上是64位类型。在大多数32位系统上仍然只有32位,因此您需要使用 off_t
的 ftello
来能够便携地处理大文件。尽管 ISO C 选择不定义行为,但大多数实现确实如此,在大多数系统上实际上可以工作。 - Peter CordesPOSIX标准有自己的方法来获取文件大小。
使用sys/stat.h
头文件来调用该函数。
stat(3)
获取文件统计信息。st_size
属性。注意:它将文件大小限制为4GB
。如果不是Fat32
文件系统,则使用64位版本!
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, char** argv)
{
struct stat info;
stat(argv[1], &info);
// 'st' is an acronym of 'stat'
printf("%s: size=%ld\n", argv[1], info.st_size);
}
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, char** argv)
{
struct stat64 info;
stat64(argv[1], &info);
// 'st' is an acronym of 'stat'
printf("%s: size=%ld\n", argv[1], info.st_size);
}
ANSI C 并没有直接提供确定文件长度的方法。
我们需要动动脑筋。现在,我们将使用寻找的方法!
#include <stdio.h>
int main(int argc, char** argv)
{
FILE* fp = fopen(argv[1]);
int f_size;
fseek(fp, 0, SEEK_END);
f_size = ftell(fp);
rewind(fp); // to back to start again
printf("%s: size=%ld", (unsigned long)f_size);
}
stdin
或管道,POSIX,ANSI C将无法工作。
它将返回0
,如果文件是管道或stdin
。
观点:
您应该使用POSIX标准。因为它支持64位。struct _stat64
和__stat64()
用于编程。 - Bob Steinfopen
需要两个参数。 - M.Mftell
函数只能保证在以二进制模式打开文件时返回从文件开头到当前位置的字节数。然而,在文本模式下,ftell
返回的值是未指定的,并且仅对 fseek
有意义。 - Andreas Wenzel#include <sys/stat.h>
off_t fsize(char *file) {
struct stat filestat;
if (stat(file, &filestat) == 0) {
return filestat.st_size;
}
return 0;
}
如果您正在构建Windows应用程序,请使用GetFileSizeEx API,因为CRT文件I/O在确定文件长度方面很混乱,这是由于不同系统上文件表示的特殊性造成的。 ;)
我使用以下代码来查找文件长度。
//opens a file with a file descriptor
FILE * i_file;
i_file = fopen(source, "r");
//gets a long from the file descriptor for fstat
long f_d = fileno(i_file);
struct stat buffer;
fstat(f_d, &buffer);
//stores file size
long file_length = buffer.st_size;
fclose(i_file);
stat
或Microsoft Windows上的GetFileSize
。fseek( fp, 0, SEEK_END );
long size = ftell( fp );
long
足够大以表示文件大小(这在某些平台上是值得怀疑的,尤其是微软Windows),发布的代码存在以下问题:ftell
返回的文件位置指示器的值包含未指定的信息。仅对于二进制流,此值保证是从文件开头算起的字符数。对于文本流没有这样的保证。SEEK_END
。long
足够大以表示文件大小,则发布的代码将有效。\r\n
(回车后跟换行)将被翻译为\n
用于文本流(但不适用于二进制流),因此您得到的文件大小将计算\r\n
为两个字节,尽管您在文本模式下只读取了一个字符(\n
)。因此,您得到的结果将不一致。long
只有4个字节,这意味着对于大于2GB的文件,ftell()
将会失败。 - Andrew Henle
char* file
,而不是FILE* file
?-1 - user12211554strlen
函数! - user26742873