- List item
在C语言中,任何程序运行后称为进程执行时默认会打开三个输入输出流:stdin、stdout、stderr;stdin:标准输入,对应设备:键盘、stdout:标准输出,对应设备:显示器、stderr:标准错误,对应设备:显示器
注意:读写位置在起始位置,注意不要覆盖写入,文件内容有可能会有空字符(\0),从文件读取数据进行处理;
系统文件I/O
系统接口主要是这几个,分别是:read、write、open、lseek、close
- open
先使用man手册查看open的使用方法,例如:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode)
open函数是不定参函数,实际上只有一个;
其中pathname表示要打开或者创建的目标文件名称,flags表示以什么方式打开,可以传入多个参数选项,参数有:
O_RDONLY:只读打开
O_WRONLY:只写打开
O_RDWR:可读可写打开
这三个宏,必须指定一个且只能指定一个(必选参数)
可选参数:
O_APPEND:追加写
O_CREAT:若文件不存在,则创建它,需要使用mode选项,来指明新文件的访问权限
O_EXCL:通常与O_CREAT同时使用表示文件不存在则创建,已经存在则报错返回;
O_TRUNC;打开文件的同时,清空文件原有内容;
因此C语言中r+相当于O_RDWR,w+相当于O_RDWR|O_TRUNC|O_CREAT,a+相当于O_RDWR|O_CREAT|O_APPEND;
例如:
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
umask(0);
int fd=open("log.txt",O_WRONLY|O_CREAT,0);
if(fd<0)
{
printf("open error");
return 0;
}
close(fd);
}
在这里我们将mode(权限)先指定为0,因为当前目录并不存在log.txt文件,因此要使用O_CREAT宏,进行按位或运算,运行结果是
[Daisy@localhost LinuxCode]$ cat log.txt
cat: log.txt: 权限不够
可以看到这时权限不够,因为这时传的mode是0,这时将mode改成
int fd=open("log.txt",O_WRONLY|O_CREAT,0644);
这时运行得到log.txt的权限的确是644:
-rw-r--r--. 1 Daisy Daisy 0 10月 17 18:41 log.txt
这时就可以进行写操作了,例如:
1 #include <stdio.h>
2 #include <errno.h>
3 #include <string.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 #include <unistd.h>
8 int main()
9 {
10 int fd=open("log.txt",O_WRONLY|O_CREAT,0644);
11 if(fd<0)
12 {
13 printf("open error");
14 return 0;
15 }
16 const char* msg="hello bit\n";
17 write(fd,msg,strlen(msg));
18 close(fd);
19
20 }
此时运行成功后可以看到log.txt的内容是:
[Daisy@localhost LinuxCode]$ cat log.txt
hello bit
发现的确写进去了。那么这个fd是什么呢,例如:
1 #include <stdio.h>
2 #include <errno.h>
3 #include <string.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 #include <unistd.h>
8 int main()
9 {
10 int fd0=open("log0.txt",O_WRONLY|O_CREAT,0644);
11 int fd1=open("log1.txt",O_WRONLY|O_CREAT,0644);
12 int fd2=open("log2.txt",O_WRONLY|O_CREAT,0644);
13 int fd3=open("log3.txt",O_WRONLY|O_CREAT,0644);
14 int fd4=open("log4.txt",O_WRONLY|O_CREAT,0644);
15 int fd5=open("log5.txt",O_WRONLY|O_CREAT,0644);
16 //if(fd<0)
17 // {
18 // printf("open error");
19 // return 0;
20 // }
21 printf("fd0:%d\n",fd0);
22 printf("fd1:%d\n",fd1);
23
24 printf("fd2:%d\n",fd2);
25 printf("fd3:%d\n",fd3);
26 printf("fd4:%d\n",fd4);
27 printf("fd5:%d\n",fd5);
28 // const char* msg="hello bit\n";
29 // write(fd,msg,strlen(msg));
30 close(fd0);
31 close(fd1);
32 close(fd2);
33 close(fd3);
34 close(fd4);
35 close(fd5);
36 }
发现fd(文件描述符)是:
[Daisy@localhost LinuxCode]$ ./mywrite
fd0:3
fd1:4
fd2:5
fd3:6
fd4:7
fd5:8
[Daisy@localhost LinuxCode]$ ./mywrite
fd0:3
fd1:4
fd2:5
fd3:6
fd4:7
fd5:8
发因此可以得出结论:一个进程默认打开三个文件描述符,分别叫做0 1 2,0对应标准输入,1对应标准输出,2对应标准错误,比如:
8 int main()
9 {
10
11 const char* msg="hello bit\n";
12 write(1,msg,strlen(msg));
13 }
这时就是写入到了标准输出,结果是:
[Daisy@localhost LinuxCode]$ ./mywrite
hello bit
- write
它的函数原型是:
ssize_t write(int fd, const void *buf, size_t count);
其中参数fd表示文件描述符,buf表示从buf中写入到fd中,count表示写了多少字节的数据,它的返回值表示成功返回所写的字节数,若为0表示没有写入数据;
- read
它的函数原型是:
ssize_t read(int fd, void *buf, size_t count);
其中参数表示文件描述符,buf表示从fd中读取的数据放在buf中,count表示读取了多少字节,返回值成功返回读取到的字节数,为0表示文件描述符,此返回值受文件剩余字节数限制.当返回值小于指定的字节数时并不意味着错误;这可能是因为当前可读取的字节数小于指定的字节数(比如已经接近文件结尾,或者正在从管道或者终端读取数据,或者 read()被信号中断). 发生错误时返回-1,并置 errno 为相应值.在这种情况下无法得知文件偏移位置是否有变化;
例如:
1 #include <stdio.h>
2 #include <errno.h>
3 #include <string.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 #include <unistd.h>
8 int main()
9 {
10 int fd=open("log0.txt",O_RDONLY);
11 if(fd<0)
12 {
13 printf("open error\n");
14 }
15 char c;
16 while(read(fd,&c,1)>0)
17 {
18 putchar(c);
19 }
20 close(fd);
21 return 0;
22 }
这时就可以读出log0.txt中的内容,结果是:
[Daisy@localhost LinuxCode]$ ./mywrite
hello world!
hello world!
hello world!
的确读出了log0.txt中的内容,read的返回值为0时退出循环。
再例如:
1 #include <stdio.h>
2 #include <errno.h>
3 #include <string.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 #include <unistd.h>
8 int main()
9 {
10 int fd=open("log0.txt",O_RDONLY);
11 if(fd<0)
12 {
13 printf("open error\n");
14 }
15 char c[1024];
16 ssize_t s=read(fd,c,1024);
17 if(s>0)
18 {
19 c[s]=0;//因为read不是C中的函数,不能保证将\0读到c中
20 printf("s:%d\n",s);
21 printf("%s\n",c);
22 }
23 close(fd);
24 return 0;
25 }
此时的运行结果是:
[Daisy@localhost LinuxCode]$ ./mywrite
s:39
hello world!
hello world!
hello world!
发现也的确读出了log0.txt中的内容。
- lseek
它的函数原型是:
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
其中参数fd是文件描述符,offset表示偏移量,whence与C语言中的fseek一样;