当前的计算系统除了包括对数据有 加工和处理 以外还有 搬运
这个 搬运 代表着 输入和输出 ,及 input/output ,简称 I/O
UNIX/Linux 的缔造者们将数据的 来源和目标 都抽象为 文件,所以在 UNIX/Linux 系统中 一切皆文件
一切皆文件 不仅仅对磁盘,还包括鼠标,键盘,显示器这些设备,那么对这些设备的操作也都抽象成了对 文件的I/O操作
关于 标准I/O 可以参看之前的文章 《标准I/O (一)》 ,类Unix系统中除了 标准I/O 还有 文件I/O,可以完成相同工作,关于 文件I/O 还有它们之间的区别可以参看之前的文章 《文件I/O (一)》,关于C语言的API(linux)可以参看 Linux C API 参考手册 在线文档
这里分享一下我在学习 文件 I/O 库过程中的笔记和心得
下面是一些 文件IO库 中的常用函数
int open( const char *pathname, int flags)
int open( const char *pathname, int flags, mode_t mode)
ssize_t read(int fd, void *buf, size_t count)
ssize_t write(int fd, const void *buf, size_t count)
off_t lseek(int fildes, off_t offset, int whence)
int close(int fd)
结构体定义
struct stu
{
int id;
char name[5];
int score;
};
要求:用非缓冲IO实现
#include <stdio.h>
#include <unistd.h> //文件IO函数包含其中,缺少这个头文件read,write,close 会报错
#include <fcntl.h> //open函数包含其中,还有一些重要的宏定义
typedef struct student //student 结构体定义
{
int id;
char name[5];
int score;
}ST;
int main()
{
int res=-1,fa=0,fb=0,maxscore=0,tscore=0,i=0;
char *fileA="f1";
char *fileB="f2"; //变量定义与初始化
ST stutmp,stu[5]={
{11,"xiao",18},
{13,"hong",88},
{16,"tuna",98},
{19,"tony",60},
{90,"duno",98}
};
if (-1==(fa=open(fileA,O_RDWR|O_CREAT|O_TRUNC,0644))) //以读写方式打开文件A
{
printf("cannot open file:%s\n",fileA);
return res;
}
if (-1==(fb=open(fileB,O_RDWR|O_CREAT|O_TRUNC,0644))) //以读写方式打开文件B
{
printf("cannot open file:%s\n",fileB);
return res;
}
if(sizeof(ST)*5 != write(fa,stu,sizeof(ST)*5)) //将结构体数组所有内容写到文件A ,顺利的情况下会返回实际写入的字节数,利用这个特性来判断有没写成功
{
printf("write error on:%s\n",fileA);
return res;
}
lseek(fa,sizeof(ST)-sizeof(int),SEEK_SET); //将文件指针定位到分数的部分,SEEK_SET 代表的是0,这个宏是在fcntl.h中定义的,意思是偏移量相对位置为文件的开头
if(sizeof(int)!=read(fa,&maxscore,sizeof(int))) //将分数读到maxscore中,作为初始的最大分数
{
printf("read error on:%s\n",fileA);
return res;
}
lseek(fa,sizeof(ST)-sizeof(int),SEEK_SET); //重新将文件指针定位到分数的部分
for(i=0;i<5;i++)
{
if(sizeof(int) != read(fa,&tscore,sizeof(int))) //将分数写到tscore中
{
printf("read error on:%s\n",fileA);
return res;
}
if(maxscore < tscore) maxscore=tscore; //将分数与初始的maxscore进行比较,如果当前分数较大,则替换掉maxscore中的值
lseek(fa,sizeof(ST)-sizeof(int),SEEK_CUR); //从当前位置开始,定位到下一个分数处,SEEK_CUR代表的是1,这个宏是在fcntl.h中定义的,意思是偏移量相对位置为当前位置
}
lseek(fa,sizeof(ST)-sizeof(int),SEEK_SET); //重新将文件指针定位到第一个分数的位置
for(tscore=0,i=0;i<5;i++)
{
if(sizeof(int) != read(fa,&tscore,sizeof(int))) //将分数写到tscore中
{
printf("read error on:%s\n",fileA);
return res;
}
if(maxscore == tscore) //如果tscore与maxscore相等,就读取这个结构体的内容,并将这个结构体的内容写到文件B中
{
lseek(fa,-1*sizeof(ST),SEEK_CUR); //从当前位置后退一个结构体的长度,注意 -1*与SEEK_CUR的用法
if (sizeof(ST) != read(fa,&stutmp,sizeof(ST))) //读取这个结构体的内容到stutmp中
{
printf("read error on:%s\n",fileA);
return res;
}
if(-1 == write(fb,&stutmp,sizeof(ST))) //将stutmp中的内容写到文件B中
{
printf("write error on:%s\n",fileB);
return res;
}
}
lseek(fa,sizeof(ST)-sizeof(int),SEEK_CUR); //定位到下一个分数的部分
}
close(fa);
close(fb);
res=0;
return res;
}
Note: 文件打开数是一种系统资源,是有上限的,虽然程序退出后,系统会帮忙清理,但在程序设计中,打开文件,使用完后进行手动关闭是一种很好的习惯,这样可以有效避免缓存未刷新的潜在隐患,也可以更加节约资源
emacs@ubuntu:~/c$ ll f1
ls: 无法访问f1: 没有那个文件或目录
emacs@ubuntu:~/c$ ll f2
ls: 无法访问f2: 没有那个文件或目录
emacs@ubuntu:~/c$ alias gtc
alias gtc='gcc -Wall -g -o'
emacs@ubuntu:~/c$ gtc savetofile.x savetofile.c
emacs@ubuntu:~/c$ ./savetofile.x
emacs@ubuntu:~/c$ ll f1
-rw-r--r-- 1 emacs emacs 80 2016-12-30 04:08 f1
emacs@ubuntu:~/c$ ll f2
-rw-r--r-- 1 emacs emacs 32 2016-12-30 04:08 f2
emacs@ubuntu:~/c$ xxd f1
0000000: 0b00 0000 7869 616f 0000 0000 1200 0000 ....xiao........
0000010: 0d00 0000 686f 6e67 0000 0000 5800 0000 ....hong....X...
0000020: 1000 0000 7475 6e61 0000 0000 6200 0000 ....tuna....b...
0000030: 1300 0000 746f 6e79 0000 0000 3c00 0000 ....tony....<...
0000040: 5a00 0000 6475 6e6f 0000 0000 6200 0000 Z...duno....b...
emacs@ubuntu:~/c$ xxd f2
0000000: 1000 0000 7475 6e61 0000 0000 6200 0000 ....tuna....b...
0000010: 5a00 0000 6475 6e6f 0000 0000 6200 0000 Z...duno....b...
emacs@ubuntu:~/c$
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。