文件长度和文件截短
转自 http://blog.csdn.net/todd911/article/details/12068105
1.文件长度
stat结构的st_size成员以字节为单位表示文件的长度,此字段只对普通文件,目录文件和符号链接有意义。stat结构的st_blksize成员是对文件IO较合适的块长度,在介绍系统IO调用时,该值为4096B。stat结构的st_blocks成员是所分配的实际512字节块数量。
实践:
#include <stdio.h> #include <sys/stat.h> int main(int argc, char * argv[]){ struct stat buf; if(argc != 2){ printf("you must specify one parameter.\n"); return -1; } if(lstat(argv[1],&buf) < 0){ perror("stat"); return -1; } printf("st_size:%ld\n",buf.st_size); printf("st_blksize:%ld\n",buf.st_blksize); printf("st_blocks:%ld\n",buf.st_blocks); }
运行结果:
$ ./a.out a.out
st_size:7526
st_blksize:4096
st_blocks:16
st_size:7526
st_blksize:4096
st_blocks:16
$ ll a.out
-rwxrwxr-x 1 yan yan 7526 Jun 12 15:53 a.out*
-rwxrwxr-x 1 yan yan 7526 Jun 12 15:53 a.out*
文件大小:7526字节,文件块大小:4096字节,512块数量:16
如果是空洞文件,stat中保存的大小是多少呢?
下面是一个包含空洞的文件,10个字节+40960个字节空洞+10个字节。
$ ll a.txt
-rw------- 1 yan yan 40980 Jun 12 16:00 a.txt
-rw------- 1 yan yan 40980 Jun 12 16:00 a.txt
$ du -h a.txt
8.0K a.txt
8.0K a.txt
执行上面的程序进行大小的测定:
$ ./a.out a.txt
st_size:40980
st_blksize:4096
st_blocks:16
st_size:40980
st_blksize:4096
st_blocks:16
虽然st_size是40980字节,但是st_blocks还是16(16*512=8192字节)
如果是符号链接文件,则stat保存的大小是多少呢?
下面是一个符号链接文件:
$ ll symblicfile
lrwxrwxrwx 1 yan yan 7 Jul 10 07:21 symblicfile -> desfile
lrwxrwxrwx 1 yan yan 7 Jul 10 07:21 symblicfile -> desfile
执行上面的程序进行大小的测定:
$ ./a.out symblicfile
st_size:7
st_blksize:4096
st_blocks:0
st_size:7
st_blksize:4096
st_blocks:0
文件大小是文件名desfile的长度,正好是7个字节。
2.文件截断
下面2个函数将现有的文件长度截短成指定的字节数:
#include<unistd.h> int truncate(const char* pathname, off_t length); int ftruncate(int filedes, off_t length);
若成功则返回0,若出错则返回-1
实践:
#include <stdio.h> #include <unistd.h> #include <fcntl.h> int main(void){ if(truncate("a.txt",5)<0){ perror("truncate"); return -1; } int fd = -1; if((fd = open("b.txt",O_RDWR))<0){ perror("open"); return -1; } if(ftruncate(fd,8)<0){ perror("ftruncate"); return -1; } if(fd != -1){ close(fd); } return 0; }
运行结果:
$ ll a.txt b.txt
-rw-rw-r-- 1 yan yan 10 Jul 10 07:11 a.txt
-rw-rw-r-- 1 yan yan 10 Jul 10 07:11 b.txt
-rw-rw-r-- 1 yan yan 10 Jul 10 07:11 a.txt
-rw-rw-r-- 1 yan yan 10 Jul 10 07:11 b.txt
$ ./a.out
$ ll a.txt b.txt
-rw-rw-r-- 1 yan yan 5 Jul 10 07:12 a.txt
-rw-rw-r-- 1 yan yan 8 Jul 10 07:12 b.txt
$ ll a.txt b.txt
-rw-rw-r-- 1 yan yan 5 Jul 10 07:12 a.txt
-rw-rw-r-- 1 yan yan 8 Jul 10 07:12 b.txt
如果length的大小是负数呢?
#include <stdio.h> #include <unistd.h> #include <fcntl.h> int main(void){ if(truncate("a.txt",-1)<0){ perror("truncate"); return -1; } return 0; }
运行结果:
$ ll a.txt
-rw-rw-r-- 1 yan yan 5 Jul 10 07:12 a.txt
yan@yan-vm:~/apue$ ./a.out
truncate: Invalid argument
-rw-rw-r-- 1 yan yan 5 Jul 10 07:12 a.txt
yan@yan-vm:~/apue$ ./a.out
truncate: Invalid argument
如果length的值大于文件的大小呢?
#include <stdio.h> #include <unistd.h> #include <fcntl.h> int main(void){ if(truncate("a.txt",10)<0){ perror("truncate"); return -1; } return 0; }
运行结果:
$ ll a.txt
-rw-rw-r-- 1 yan yan 5 Jul 10 07:12 a.txt
$ ./a.out
$ ll a.txt
-rw-rw-r-- 1 yan yan 10 Jul 10 07:15 a.txt
yan@yan-vm:~/apue$ od -c a.txt
0000000 1 2 3 4 5 \0 \0 \0 \0 \0
0000012
-rw-rw-r-- 1 yan yan 5 Jul 10 07:12 a.txt
$ ./a.out
$ ll a.txt
-rw-rw-r-- 1 yan yan 10 Jul 10 07:15 a.txt
yan@yan-vm:~/apue$ od -c a.txt
0000000 1 2 3 4 5 \0 \0 \0 \0 \0
0000012
文件被自动填充为\0