UNIX编程-文件大小获取

Posted by 周思进 on April 4, 2022

一、命令创建测试文件

方式一
truncate -s 400M test.file
方式二
dd if=/dev/urandom of=test2.file bs=20M count=20


二、命令查看文件大小

方式一、ls 命令
$ ls -lh test.file
-rw-r--r-- 1 501 dialout 400M 4月   3 13:36 test.file
方式二、du 命令

du 命令查看的是文件实际占用的磁盘空间大小

$ du -h test.file
0	test.file
$ du -h test2.file
401M	test2.file

可以看到前面通过方式1创建的文件,实际并没有占用磁盘空间,而方式2创建的文件,则是实实在在的占用了磁盘空间。

对于test.file,只有实际写入数据后,文件系统才会为该文件分配磁盘空间,在这之前,都属于文件空洞。

方式三、stat 命令
$ stat test.file
  文件:test.file
  大小:419430400 	块:0          IO 块:65536  普通文件
  
stat test2.file
  文件:test2.file
  大小:419430400 	块:819920     IO 块:65536  普通文件

stat 命令同样可以看出文件实际占用的磁盘块

方式四、wc 命令
$ wc -c test.file
419430400 test.file

显示该文件的字节数


三、编程获取文件大小

方式一、lseek
int fun_seek(void)
{
	int fd = -1;
	int len = 0;

	fd = open("./test.file", O_RDONLY);
    len = lseek(fd, 0, SEEK_END);
	printf("[FILE:%s] [FUNC:%s] [Line:%d]  len:%d  \n", __FILE__, __func__, __LINE__ , len);
    close(fd);

    fd = open("./test2.file", O_RDONLY);
    len = lseek(fd, 0, SEEK_END);
	printf("[FILE:%s] [FUNC:%s] [Line:%d]  len:%d  \n", __FILE__, __func__, __LINE__ , len);
    close(fd);

	return 0;
}
方式二、fstat
int fun_fstat(void)
{
    int fd = -1;
	struct stat buf = {0};

	fd = open("./test.file", O_RDONLY);
	fstat(fd, &buf);
	printf("[FILE:%s] [FUNC:%s] [Line:%d]  filesize:%lld st_blksize:%lld \n", __FILE__, __func__, __LINE__ , buf.st_size, buf.st_blocks);
    close(fd);

    fd = open("./test2.file", O_RDONLY);
	fstat(fd, &buf);
	printf("[FILE:%s] [FUNC:%s] [Line:%d]  filesize:%lld st_blksize:%lld \n", __FILE__, __func__, __LINE__ , buf.st_size, buf.st_blocks);
    close(fd);

	return 0;
}
方式三、ftell
int fun_ftell(void)
{
    FILE *file = NULL;
	int len = 0;

	file = fopen("./test.file", "r");
    fseek(file, 0, SEEK_END);
    len = ftell(file);
	printf("[FILE:%s] [FUNC:%s] [Line:%d]  len:%d  \n", __FILE__, __func__, __LINE__ , len);
    fclose(file);

    file = fopen("./test2.file", "r");
    fseek(file, 0, SEEK_END);
    len = ftell(file);
	printf("[FILE:%s] [FUNC:%s] [Line:%d]  len:%d  \n", __FILE__, __func__, __LINE__ , len);
    fclose(file);

	return 0;
}

运行结果:

./a.out 
[FILE:test.c] [FUNC:fun_seek] [Line:18]  len:419430400  
[FILE:test.c] [FUNC:fun_seek] [Line:23]  len:419430400  
[FILE:test.c] [FUNC:fun_fstat] [Line:36]  filesize:419430400 st_blksize:0 
[FILE:test.c] [FUNC:fun_fstat] [Line:41]  filesize:419430400 st_blksize:819920 
[FILE:test.c] [FUNC:fun_ftell] [Line:55]  len:419430400  
[FILE:test.c] [FUNC:fun_ftell] [Line:61]  len:419430400

综合对比,使用fstat接口不仅简单,而且针对文件空洞,可以确认实际占用多少磁盘空间;而使用 lseek 之后,如后面还要进行读写操作,还需要将读写指针(读和写是同一个指针)重置回来,fstat 就不会有这样的麻烦。