首先介绍文件操作的几个函数:
open() close() read() write() lseek()
补充:文件的默认权限 -rw- rw- r-- 对应的8进制的代码 0664;
补充:前面讲过每个进程都有自己的PID,而每个进程也都有自己的PCB,成为进程控制块,他里面记录了进程用了哪些资源。
补充:文件描述符-它存在于进程控制块中,以一个数组的形式记录进程打开过的文件(打开的文件也是进程使用到的资源),每打开一个就往数组里放进文件的地址,从数组下标0开始依次放。 数组的下标就叫做该文件的描述符。可以理解为控制块是一个大的结构体,而存放打开过文件的地址的数组只是其中一个元素。
默认的文件描述符:
0:标准输入 键盘 STDIN_FILENO
1:标准输出 显示器 STDOUT_FILENO
2标准错误输出 显示器 STDERR_FILENO
首先open()函数:
#includ e <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags, mode_t mode)
功能:打开或者创建一个文件
参数:pathname-文件名字
flags:
O_RDONLY 只读方式打开文件
O_WRONLY 只写方式打开文件
O_RDWR 可读可写方式打开文件
文件的创建标记和文件的状态标记可以在flags中 可以按位或|0个或多个
文件创建标记:
O_CREAT:如果文件不存在就创建文件.当falgs中指定时后边必须用mode指定文件权限, mode表示创建的文件的权限(mode & ~umask)
O_EXCL:如果这个标记和O_CREAT一起使用并且,要创建的文件已经存在,就会报错
O_TRUNC:如果标记被指定,打开的文件已经存在,并且是普通文件,打开的时候有写的权限,就会将这个文件中的内容全部清为0;
文件状态标记:
O_APPEND:以追加的方式打开文件.文件写的位置定位在文件的末尾
返回值:fd-文件描述符
close()函数
#include <unistd.h>
int close(int fd);
功能:关闭一个文件描述符
参数:fd-要关闭的文件的描述符
返回值:成功关闭返回0,否则-1
read()函数
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
功能:read() 从文件描述符 fd 中读取 count 字节的数据并放入从 buf开始的缓冲区中
参数:fd-要读的文件的描述符
buf-读的数据放入的存储区
count-需要读取的字节数
返回值:读取到的字节数,当返回值小于count时,不是错误,而是文件中剩余字节数小于count的值。读取错误是返回-1.
write()函数
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
功能:write 向文件描述符 fd 所引用的文件中写入 从 buf 开始的缓冲区中 count字节的数据
参数:fd-文件描述符
buf-buf存储区的首地址
count-要写入的字节数
返回值:成功返回写入的字节数,失败返回-1;
lseek()函数
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
功能:重新定位读和写的位置
参数:fd-要操作的文间的描述符
offset-偏移量
whence-从哪里开始偏移。有如下参数。
SEEK_SET:文件的开头
SEEK_CUR:当前的读写位置
SEEK_END:代表了文件的末尾
返回值:成功返回从文件开头到offset的位置,失败返回-1。
下面代码演示:
读一个文件并显示,然后把读的文件写进另一个文件的程序:
1 #include<stdio.h>
2 #include<sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 int file(char *argv1,char *argv2){
6 int fd=open(argv1,O_RDONLY);
7 int fd1=open(argv2,O_RDWR|O_CREAT|O_EXCL,0664);
8 int arr[8]={0};
9 if(fd==-1 || fd1==-1){
10 perror("open1");
11 return -1;
12 }
13 while((read(fd,arr,8))>0){
14 write(fd1,arr,8);
15 printf("%s",(char *)arr);
16 }
17 close(fd);
18 close(fd1);
19 return 0;
20 }
21 int main(int argc,char *argv[1]){ //读的文件为argv[1] 写进的新文件为argv[2]
22 if(argc!=3){
23 printf("输入错误!请重新输入!\n");
24 return -1;
25 }
26 file(argv[1],argv[2]);
27 return 0;
28 }
运行结果如下:
tarena@ubuntu:~/LIANXI/10.15$ ./a.out file.c a.c
#include<stdio.h>
#include<sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int file(char *argv1,char *argv2){
int fd=open(argv1,O_RDONLY);
int fd1=open(argv2,O_RDWR|O_CREAT|O_EXCL,0664);
int arr[8]={0};
if(fd==-1 || fd1==-1){
perror("open1");
return -1;
}
while((read(fd,arr,8))>0){
write(fd1,arr,8);
printf("%s",(char *)arr);
}
close(fd);
close(fd1);
return 0;
}
int main(int argc,char *argv[1]){
if(argc!=3){
printf("输入错误!请重新输入!\n");
return -1;
}
file(argv[1],argv[2]);
return 0;
}
tarena@ubuntu:~/LIANXI/10.15$ ls
a.c a.out file.c
以上就是文件操作的相关函数! 以上代码相当于实现了cp功能
下面介绍文件的输出重定向:
函数 dup() dup2()
#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);
dup()
功能:将原文件的文件描述符复制,并将复制的描述符放在新创建的文件描述符里
参数:oldfd-原文件描述符
返回值:成功-复制后的文件描述符 失败返回-1。
dup2()
功能:复制一个文件描述符
参数:oldfd-会被覆盖的文件描述符 newfd-用于去覆盖的文件描述符
返回值:成功-被覆盖过后的描述符 失败返回-1
程序如下:
1 #include<stdio.h>
2 #include <unistd.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <fcntl.h>
6 int main(){
7 int fd=open("b.c",O_RDWR);
8 if(fd==-1){
9 perror("open");
10 return -1;
11 }
12 int fd_new=dup(1);
13 char buf[8];
14 read(fd,buf,8);
15 dup2(fd,1);
16 write(fd_new,buf,8);
17 dup2(fd_new,1);
18 close(fd);
19 close(fd_new);
20 return 0;
21 }
运行结果为:
tarena@ubuntu:~/LIANXI/10.15$ ./a.out
1q2w3e4
tarena@ubuntu:~/LIANXI/10.15$
图解:
从图中可以看到,我们先用dup函数将1复制到下表为4那里,再用dup2函数将3复制到下表为1那里。现在向下标为4那里写入字符就可以输出。完成了输出重定向。
剧终!