文件/目录管理(1)---open()/close()/read()/write()
2016-06-16 10:46
447 查看
一 文件管理
在Linux中,几乎一切都被看成了文件,因此文件操作函数(系统调用):open()/close()/read()/write()/ioctl()
可以操作几乎所有输入输出设备。
1 open()函数
open() 打开一个文件int open(char* filename,int flag,…)
filename 表示文件名(带路径)
flag 是打开的标识,可以选择打开方式,常见值
O_RDONLY O_WRONLY O_RDWR - 选择打开的权限
O_CREAT - 如果不存在会新建,存在则打开
O_TRUNC -和O_CREAT结合使用,打开时清空文件
O_EXCL -和O_CREAT结合使用,但文件存在时不打开,而是返回 -1 代表错误
O_APPEND - 追加的方式打开文件
… 代表0-n个任意类型的参数,如果是新建文件需要第三个参数,如果只是打开文件不需要第三个参数,新建文件时,第三个参数是新建文件的权限(必须)。
返回文件描述符,-1代表出错。
文件描述符本身就是一个非负整数,代表一个打开的文件。
文件open的过程:
先打开一个文件 -> 用文件表记录该文件信息 ->在文件描述符总表中,找没使用的文件描述符(默认找最小) -> 把最小的文件描述符和文件表对应起来,放入文件描述符总表中。
文件描述符0 1 2被系统占用,分别代表标准输入、标准输出和标准错误,打开文件的描述符从3 开始。
open.c #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> int main(){ printf("O_RDONLY=%d,O_WRONLY=%d,O_RDWR=%d\n" ,O_RDONLY,O_WRONLY,O_RDWR); printf("O_CREAT=%d\n",O_CREAT); printf("O_APPEND=%d\n",O_APPEND); int fd = open("a.txt",O_CREAT|O_RDWR,0666); if(fd==-1) perror("open"),exit(-1); printf("fd=%d\n",fd); int fd2 = open("a.txt",O_RDONLY); printf("fd2=%d\n",fd2); close(fd); close(fd2); }
2 read()和write()
read() 和 write() ,读数据和写数据三个参数:
第一个参数 fd
第二个参数 void*
第三个参数 read() 用sizeof(),write()用实际想写入的字节数
write.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> int main(){ int fd = open("a.txt",O_CREAT|O_RDWR,0666); if(fd==-1) perror("open"),exit(-1); int res = write(fd,"hello",5); if(res==-1) perror("write"),exit(-1); printf("写了%d字节数据\n",res); close(fd);//写 int fd2 = open("a.txt",O_RDONLY);//读 if(fd2==-1) perror("open"),exit(-1); char buf[100] = {}; res = read(fd2,buf,sizeof(buf)); if(res==-1) perror("read"),exit(-1); printf("读到了%d字节,内容:%s\n",res,buf); close(fd2); }
下面是用read()和write()写的两个小练习。
1 实现文件的复制
copy.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> int main(){ //新建文件时,有预设的文件权限屏蔽(002),umask int fd = open("a.txt",O_RDONLY);//读文件 if(fd==-1) perror("open"),exit(-1); char buf[100] = {}; int fd2 = open("b.txt",//写文件 O_CREAT|O_RDWR|O_TRUNC,0666);//O_APPEND if(fd2==-1) perror("open2"),exit(-1); while(1){ int res = read(fd,buf,sizeof(buf)); if(res <= 0) break; write(fd2,buf,res); } close(fd); close(fd2); }
2 把员工信息写入文件,并在另外一个文件中读出来
writeemp.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> struct emp{ int id; char name[20]; double sal; }; int main(){ int fd = open("emp.dat", O_CREAT|O_RDWR|O_TRUNC,0666); if(fd==-1) perror("open"),exit(-1); struct emp em = {100,"zhangfei",12000.0}; int res = write(fd,&em,sizeof(em)); if(res==-1) perror("write"),exit(-1); printf("写入员工信息成功\n"); close(fd); } reademp.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> struct emp{ int id; char name[20]; double sal; }; int main(){ int fd = open("emp.dat",O_RDONLY); if(fd==-1) perror("open"),exit(-1); struct emp em; int res = read(fd,&em,sizeof(em)); if(res==-1) perror("read"),exit(-1); printf("%d,%s,%lf\n",em.id,em.name,em.sal); close(fd); }
趣味练习:
把员工信息写入文件,要求用cat/vi能看清楚信息
提示:
只有字符串类型才能被vi看清楚。
把员工信息拼接成一个很长的字符串再写入文件
sprintf() 和printf() fprintf() 用法基本一样
empws.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h> struct emp{ int id; char name[20]; double sal; }; int main(){ int fd = open("emp.dat", O_RDWR|O_CREAT|O_TRUNC,0666); if(fd==-1) perror("open"),exit(-1); struct emp em = {100,"zhangfei",12000.0}; char buf[100] = {}; sprintf(buf,"%d,%s,%lf",em.id,em.name, em.sal); write(fd,buf,strlen(buf));//不要使用sizeof close(fd); }
用vi来编辑文本文件时,会自动在文本末尾加上‘\n’,这个可以通过ls -l查看文件的大小来发现会多一个字节。而通过write向文件中写的则不会。
test.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> int main(){ //新建文件时,有文件权限屏蔽(002) int fd = open("a.txt",O_CREAT|O_RDWR,0666); if(fd==-1) perror("open"),exit(-1); write(fd,"hello",5); close(fd); }
3 字符串相关常用操作
这里来一个小插曲,总结一下有关字符串的一些操作:string.c #include <stdio.h> #include <string.h> //字符串的基本操作 int main(){ //1 赋值 =和strcpy //2 指针操作 字符串以'\0'结尾,字符串数组以 // NULL结束 //3 字符串的拼接操作 char buf[100] = {}; char* s1 = "abc"; char* s2 = "def"; strcpy(buf,s1); strcat(buf,s2); printf("%s\n",buf); //4 字符串和其他的类型转换(转换函数) //其他类型转字符串sprintf(); //字符串转其他类型sscanf(); int i = 12345; char bufint[12] = {};//最少12 负号+10位数+\0 sprintf(bufint,"%d",i); printf("%s\n",bufint); char* st = "1234";//字符串转int int a; sscanf(st,"%d",&a); printf("a=%d\n",a); //5 其他相关函数,比如strlen() 取长度 //strcmp()/strncmp() 比较字符串 }
4 关于标C函数和UC函数的区别
标C函数都有输入/输出缓冲区,而UC函数在用户层是没有缓冲区,因此,频繁输入输出时,UC函数最好自定义一个缓冲区(char buf[])。如果对于性能没有特殊的要求,使用标C函数即可,有特殊要求,使用UC函数更好。
BiaocUc.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> //分别用标C和UC函数写100万个int int main(){ /*FILE* file = fopen("a.txt","w");//标C if(file==NULL) perror("fopen"),exit(-1); int i=0; for(i=0;i<1000000;i++){ fwrite(&i,4,1,file); //写int //fprintf(file,"%d",i);//转字符串后写 } fclose(file);*/ int fd = open("a.txt", O_RDWR|O_CREAT|O_TRUNC,0666); if(fd==-1) perror("open"),exit(-1); int i; int arr[10000] = {}; for(i=0;i<1000000;i++){ /*write(fd,&i,4);*/ arr[i%10000] = i; if((i%10000) == 9999) write(fd,arr,sizeof(arr)); } close(fd); }
相关文章推荐
- 让普通用户具备sudo执行权限-修改linux默认启动方式
- gearman性能与应用架构设计
- linux系统上的weblogic自启动
- linux下查看内存使用情况的方法总结(转)
- 在ARM 7A平台上编译OpenBTS
- linux中的进程管理
- CentOS6.7 双网卡绑定
- iperf based on linux
- sosreport命令进行系统环境收集
- 4bash中对日期的使用
- 基于树莓派的Spark集群搭建
- linux中利用sandbox自动安装MySQL
- Hadoop2.2.0安装配置手册!完全分布式Hadoop集群搭建过程~(心血之作啊~~) .
- 3对符合条件的文件和文件夹进行复制或修改
- Linux 上四个最佳的现代开源代码编辑器
- vim批量注释与取消注释,多行copy
- 【shell】变量的配置文件
- Linux下安装配置NTP时间同步服务器
- Linux时间同步+国内常用的NTP服务器地址
- docker1.9网络新特性,overlay网络实现主机间容器互联