write
作用:write系统调用用来将数据写入已经打开的文件当中
原型:
#include<unistd.h> ssize_t write(int fd,const void *buf,size_t count);
参数:将buf所指向缓冲分区的count个字节数据写入到有文件描述符fd指向的文件中。
成功:返回写入的字节数
错误:返回-1
lseek
作用:移动文件读写指针的位置
原型:
#include<sys/types.h> #include<unistd.h> off_t lseek(int fildes,off_t offset,int whence);
- 打开文件时,读写位置指文件开头
添加方式打开文件(open函数使用了O_APPEND),读写位置指向文件尾
参数:
fildes:打开的文件描述符
- offset:根据whence来移动读写位置的移动数
- whence:有三种
SEEK_SET:从文件开始计算偏移量
SEEK_CUR:从文件当前位置
SEEK_END:从文件结尾处
lseek允许文件指针的值设置到EOF后,这样并不改变文件的大小,如果使用write对EOF之后的位置写入数据后,之前的EOF处与后面已写入的数据间将存在一个间隔,用read读这个间隔时,为0。
成功:返回当前读写位置
失败:返回-1
- ##### 常用的方法
1.将文件读写指针移到文件开头
lseek(int fildes,0,SEEK_SET);
2.将文件读写指针移到文件结尾
lseek(int fildes,0,SEEK_END);
3.获取文件读写指针当前的位置(相当于文件开头的偏移)
lseek(int fildes,0,SEEK_CUR);
linux下,不允许lseek()对tty设备进行操作,此操作会返回错误代码ESPIPE
运用:
#include<stdio.h> #include<stdlib.h> #include<sys/types.h> #include<unistd.h> #include<sys/stat.h> #include<fcntl.h> #include<errno.h> /*自定义的错误处理函数*/ void my_err(const char *err_string,int line) { fprintf(stderr,"line:%d ",line); perror(err_string); exit(1); } /*自定义的读数据函数*/ int my_read(int fd) { int len; int ret; int i; char read_buf[64]; /*获取文件长度并保持文件读写指针在文件开始*/ if(lseek(fd,0,SEEK_END)==-1) my_err("lseek",__LINE__); if((len=lseek(fd,0,SEEK_CUR))==-1) my_err("lseek",__LINE__); if((lseek(fd,0,SEEK_END))==-1) my_err("lseek",__LINE__); /*读数据*/ if((ret=read(fd,read_buf,len))<0) my_err("read",__LINE__); /*打印数据*/ for(i=0;i<len;i++) printf("%c",read_buf[i]); printf("\n"); return ret; } int main(void) { int fd; char write_buf[32]="hello world!"; /*在当前目录下创建文件*/ if((fd=open("example_63.c",O_RDWR|O_CREAT|O_TRUNC,S_IRWXU))==-1) my_err("open",__LINE__); else printf("creat file success\n"); /*写数据*/ if(write(fd,write_buf,strlen(write_buf))!=strlen(write_buf)) my_err("write",__LINE__); my_read(fd); /*演示文件的间隔*/ printf("/*--------*/"); if(lseek(fd,10,SEEK_END)==-1) my_err("lseek",__LINE__); if(write(fd,write_buf,strlen(write_buf))!=strlen(write_buf)) my_err("write",__LINE__); my_read(fd); close(fd); return 0; }
- LINE 22-27:很巧妙,先将文件指针移到尾,再用SEEK_CUR计算文件的长度,再移到头
dup和dup2
作用:用来复制文件描述符
原型:
#include<unistd.h> int dup(int oldfd); int dup2(int oldfd,int newfd);
dup:用来复制oldfd指的文件描述符,复制成功时,返回最小的尚未使用的文件描述符
成功:返回新的文件描述符(和oldfd指向同一个文件,共享所有的锁定,读写指针和各项权限或标志位等)
失败:返回-1
dup2:用参数newfd指定新的文件描述符的数值
如果newfd被程序用了,系统会关闭释放该描述符
- 如果oldfd与newfd相同,返回newfd而不关闭它
- 成功:返回描述符 失败:返回-1
stat/fstat/lstat
作用:获取文件属性
原型
#include<sys/types.h> #include<sys/stat.h> #incldue<unistd.h> int stat(const char *file_name,struct stat *buf); int fstat(int filedes,struct stat *buf); int lstat(const char *file_name,struct stat *buf);
区别
fstat:通过文件描述符指定文件
- stat:获取参数file_name指定的文件名的状态信息,保存在struct stat *buf中,对于符号连接文件,返回的是符号链接文件指向的文件状态信息
lstat:对符号链接,返回链接文件本身的状态信息
成功:返回0 失败:返回-1
参数有:
struct中的东西 | 含义 |
---|---|
st_dev | 文件的设备编号 |
st_ino | 文件的i-node |
st_mode | 文件的类型和存取权限 |
st_nlink | 硬链接数目,新建立的文件值:1 |
st_uid | 文件所有者的用户id |
st_gid | 文件所有者的组id |
st_rdev | 若设备文件,则为设备编号 |
st_size | 文件大小(字节算)(符号链接:指向的文件名长度) |
st_blksize | I/O缓存区的大小 |
st_blcoks | 占用文件区块的个数,每一块大小通常为512个字节 |
st_atime | 最近一次访问的时间 |
st_mtime | 最后一次修改的时间(调用utime write才会改变) |
st_ctime | 最近一次更改的时间(此参数在文件所有者,所属组,文件权限被更改时才更新) |
st_mode包含文件类型信息:
S_ISLINK | 符号链接 |
---|---|
S_ISREG | 一般文件 |
S_ISDIR | 目录文件 |
S_ISCHR | 字符设备文件 |
S_ISBLK | 块设备文件 |
S_ISFIFO | 先进先出FIFO |
S_ISSOCK | socket |
那怎样用呢?
c
if(S_ISLNK(st_mode))
printf("l");
原因是什么?
找到他的定义,就会一目了然://将S换成F找对应的
c
#define S_ISLNK (m(((m)&&S_IFMT)==S_IFLNK)
S_ISLNK 实际是一个掩码,ta的值为017000(八进制,用来过滤出前四位 来判断文件的类型)
define S_IFMT 00170000 |
---|
define S_IFSOCK 0140000 |
define S_IFLNK 0120000 |
define S_IFREG 0100000 |
define S_IFBLK 0060000 |
define S_IFDIR 0040000 |
define S_IFCHR 0020000 |
define S_IFIFO 0010000 |
define S_ISUID 0004000 |
define S_ISGID 0002000 |
define S_ISUTX 0001000 |
* #### getcwd
作用:获取当前目录
原型:
#include<unistd.h> char *getcwd(char *buf,size_t size); char *get_current_dir_name(void); char *getwd(char *buf);
getcwd:
- 将当前工作目录绝对路径复制到参数buf指的内存空间,size为buf的空间大小(buf要足够大)
- 工作目录绝对路径的字符串长度超过size的大小,返回NULL,errno=ERANGE
- buf=NULL getcwd()根据size大小自动分配内存
- buf=NULL size=0 则根据工作目录绝对路径的字符串长度来决定配置的内存大小,用完此字符串后free掉
成功:将结果复制到buf所指的内存空间,或返回自动配置的字符串指针
失败:NULL
- #### chdir
作用:更改当前工作目录
原型:
#include<unistd.h> int chdir(const char *path); int fchdir(int fd);
(chdir):将当前工作目录改为path指定的目录
(fchdir):将当前工作目录改为由fd指定的目录
- #### opendir
只要对目录有读权限,就可以获取目录信息
作用:打开目录
原型:
#include<sys/types.h> #include<dirent.h> DIR *opendir(const char *name);
opendir用来打开参数name指定的目录,并返回DIR *形态的目录流,(类似文件描述符)
成功:返回DIR *目录流
失败:返回NULL
- #### readdir
作用:读取目录项信息,返回一个struct dirent结构的指针
原型:
#include<sys/types.h> #include<dirent.h> struct dirent *readdir(DIR *dir);
结构体里面有个d_name是指以NULL结尾的文件名
- #### closedir
作用:关闭dir指向的目录
原型:
#include<sys/types.h> #include<dirent.h> int closedir(DIR *dir);
成功:返回0
- 失败:返回-1
一定要记着打开目录后一定要关,因为在做ls的时候,因为没有关闭目录就导致了一些错误,而且这种错误不易被发现,所以一定要注意