上一期我们介绍了文件的读取(read)、写入(write)和关闭(close),这一期我们在扩充几个函数:
1、lseek函数
这个函数跟我们的鼠标光标息息相关,他可以设置光标的起始位置,那就意味着这个函数可以决定文件复制的起始位置和写入的起始位置,同样的你可以使用man 2 lseek来查看这个函数的具体信息,这里我们就不详细说明了,我们就直接将几个重要的点提一下:
//设置复制起始点
int indexr=lseek(fb1,5,SEEK_SET);
int indexw=lseek(fb2,4,SEEK_SET);
这个函数的第一个参数是文件描述符,也就是前面讲到的open的返回值,代表我们要移动光标的文件,第二个参数是移动的长度,如果是负数就是往前,正数就是往后,第三个就是光标的初始位置,有三个选项:SEEK_SET,SEEK_END,SEEK_CUR,其实看因为就可以知道大致的含义,第一个就是给光标设置位置,第二个就是从文件末尾开始移动,也就是光标会到文件末尾,第三个就是从光标当前位置移动;返回值就是光标前面的字节数,所以我们就可以使用lseek来算出文件的大小:
int content=lseek(fb2,0,SEEK_END);
可以看到这里打印的数字就是这个写入文件的大小,这个函数也是在unistd.h头文件里面的,所以使用的时候要注意自己有没有包含它;
lseek还有一个功能就是可以更改文件的大小,通过插入一些“ ”,和移动光标:
lseek(fb2,100,SEEK_CUR);
write(fb2," ",1);
通过这个函数移动光标,从当前位置向后面移动100个单位,然后在插入空格,之前这个文件的大小事2365,如果我们执行程序将会变成2465:
可以看到这里明显是扩大了大约100个单位,可能存在一些误差,但是无伤大雅;
2、stat函数
这个函数可以获取文件的属性,它在sys/stat.h的文件中,我们可以使用它来获取文件属性:
struct stat sbuf;
result=stat("readtext.txt",&sbuf);
这个函数具有两个参数,第一个是文件的名字,第二个参数要传一个结构体,当然这个结构体使我们自己定义的,但是函数执行成功之后它就会具有一下属性,如果执行失败的话就会返回-1:
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* Inode number */
mode_t st_mode; /* File type and mode */
nlink_t st_nlink; /* Number of hard links */
uid_t st_uid; /* User ID of owner */
gid_t st_gid; /* Group ID of owner */
dev_t st_rdev; /* Device ID (if special file) */
off_t st_size; /* Total size, in bytes */
blksize_t st_blksize; /* Block size for filesystem I/O */
blkcnt_t st_blocks; /* Number of 512B blocks allocated */
/* Since Linux 2.6, the kernel supports nanosecond
precision for the following timestamp fields.
For the details before Linux 2.6, see NOTES. */
struct timespec st_atim; /* Time of last access */
struct timespec st_mtim; /* Time of last modification */
struct timespec st_ctim; /* Time of last status change */
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
所以我们可以写一个程序来看看文件的属性是否正确获取到了:
#include<stdio.h>
#include<sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include<stdlib.h>
int main()
{
int fd1,result=0;
struct stat sbuf;
result=stat("readtext.txt",&sbuf);
if(result==-1)
{
perror("stat error");
exit(1);
}
printf("len=%1d\n",sbuf.st_size);
return 0;
}
执行程序之后的的确确是获取到了属性的值,而且也是正确的,这里我们获取的是readtext.txt文件的长度;
3、access函数
这个函数用来测试文件是否拥有某种权限,这个函数也是在unisted.h文件里面的,也具有两个参数:
result=access("readtext.txt",R_OK);
if(result!=-1){
printf("文件是可以阅读的\n");
}
else
{
printf("文件是不可以阅读的\n");
}
第一个参数是文件的路径名,第二个是权限,这里又三个可选项:R_OK, W_OK, F_OK, 他们分别代表的是文件的可读、可写、可执行,这里我们判断了一下可执行权限,执行之后是没有问题的:
4、chmod函数
这个函数用于修改文件的访问权限,该函数也是在sys/stat.h文件中,他也是具有两个参数,第一个参数是文件路径名,第二个是要修改的权限,这里我们传的是一个8进制数,之前我们说过文件的权限就是一个8进制数:
可以看到我们这里readtext文件的权限是rw-r-r,我们试着将他们改成rwx-rwx-rwx:
int result=0;
result=chmod("readtext.txt",0777);
if(result==-1)
{
printf("this is a error\n");
}
else
{
printf("sccessud\n");
}
我们现在chmod的第一个参数上写上我们的文件名,然后第二个参数是我们想要改成的权限,这里的7就是对应的rwx,同样他也是有一个返回值得,如果调用函数失败的话就会返回一个-1:
编译运行可以看到我们程序运行成功,再看看权限:
很明显,这里我们的权限也是的的确确修改成功了;
5、truncate函数
truncate是用来修改文件的大小的,lseek也可以修改大小,但是这个只需要调用一下就可以了,而lseek还需要写入“ ”,移动光标的操作,但是他们起到的效果是差不多的,这个函数也是具有两个参数的,第一个是文件的路径名,第二个是长度,也就是我们想要给文件设置的长度,他也是具有返回值得,如果调用失败就会返回-1:
int result=0;
result=truncate("readtext.txt",3000);
if(result==-1)
{
printf("error");
}
else
{
printf("sucessd");
}
我们这是将readtext这个文件的大小设置成3000,原来的大小是2357:
我们执行程序再来看:
可以看到这个文件已经是修改成了3000了;