我有一个程序打开一个文件,并检查其长度。
FILE* fd = fopen(argv[1], "rb"); fseek(fd, 0, SEEK_END); size_t flen = ftell(fd); if (flen == ((size_t)-1)) { printf("%s is a directory.\n", argv[1]); fclose(fd); exit(1); }
现在,至less在Linux下, fopen()
在打开目录时返回一个有效的文件描述符。 这导致查找操作返回-1
(或者,在64位系统上size_t
是无符号的, 0xFFFFFFFF
)。
不幸的是,在上面的代码( flen == ((size_t)-1)
)中的条件不能捕捉到这种情况, flen == 0xFFFFFFFF
也没有。 printf()
– 使用%x
ord %d
作为格式string的命令显示比较的两边应具有相同的值。
为什么比较运算符以这样一种奇怪的方式运行,即使双方的types相同( size_t
)? 我使用gcc 4.8.1作为编译器。
目录不存在于C99标准(或C2011标准)中。 因此,根据定义, fopen
一个目录是特定于实现的还是未定义的行为。
fopen(3)可能会失败(给出一个NULL
结果)。 fseek(3)也可能失败(通过返回-1)。 然后,你应该最好检查errno(3)或使用perror(3)
ftell
被记录为返回一个long
-1L
失败。 在64位Linux上这是0xffffffffffffffff
。
你的代码应该是相反的
FILE* fd = fopen(argv[1], "rb"); if (!fd) { perror(argv[1]); exit(EXIT_FAILURE); }; if (fseek(fd, 0, SEEK_END)<0) { perror("fseek"); exit(EXIT_FAILURE); }; long flen = ftell(fd); if (flen == -1L) { perror("ftell"); exit(EXIT_FAILURE); };
顺便说一句,在Linux / Debian / Sid / AMD64与libc-2.17和3.10.6内核,当argv[1]
是/tmp
; flen是LONG_MAX
即0x7fffffffffffffff
顺便说一下,在Linux上,目录是文件的特殊情况。 在文件路径上使用stat(2) (以及在fstat
上使用fstat
,可能从某个FILE*
fileno(3)获得)来了解更多关于某个文件的元数据,包括其“type”(通过它的模式)。 你需要opendir(3) , readdir(3)和closedir(3)来操作目录内容。 另见inode(7) 。
来自http://pubs.opengroup.org/onlinepubs/7908799/xsh/fopen.html :
The fopen() function will fail if: [EISDIR] The named file is a directory and mode requires write access.
至少在Linux上,如果你试图fopen("dirname", "wb")
你会得到一个EISDIR错误。 我也试过用d ——–访问权限的目录,我仍然得到EISDIR(而不是EACCES)。