华清远见25072班I/O学习day2

重点内容:

模块化读写(fread/fwrite)

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

功能:从stream指向的文件中读取nmemb项数据,每一项的大小为size 并且放入ptr指向的容器中

参数1:存放数据的容器,可以是任意类型的指针

参数2:每一项的大小

参数3:读取的总项数

参数4:文件指针

返回值:成功返回读取的项数,失败或者文件结束返回一个小于项数的值

注意:fread不区分到底是因为文件结束还是因为错误导致的结束,可以使用feof和ferror来判断

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

功能:将ptr指向的容器中的内容,每项为size大小的nmemb项数据,写入到stream指向的文件中

参数1:要写入的数据起始地址

参数2:每一项的大小

参数3:要写入的项数

参数4:文件指针

返回值:成功返回写入的项数,失败或者文件结束返回一个小于项数的值

有关文件指针光标的操作(fseek/ftell/rewind)

int fseek(FILE *stream, long offset, int whence);

功能:将给定的文件指针的光标进行重新定位

参数1:文件指针

参数2:偏移量(以字节为单位) >0:表示从给定的基准向后偏移 =0:表示在基准处不偏移 <0:从基准处向前偏移

参数3:基准 SEEK_SET:文件开始位置 SEEK_CUR:光标当前位置 SEEK_END:文件结尾位置

返回值:成功返回0,失败返回-1并置位错误码

long ftell(FILE *stream);

功能:求出现在文件指针光标所在位置(以字节为单位)

参数:文件指针

返回值:光标目前所在位置

eg:求一个文件的大小 1、将光标先定位到结尾:fseek(fp, 0, SEEK_END); 2、此时使用ftell的返回值,就是文件的大小:ftell(fp);

void rewind(FILE *stream);

功能:将文件光标定位到开始位置 等同于:fseek(fp, 0, SEEK_SET);

参数:文件指针

返回值:无

有关缓冲区的问题

1.对于标准IO而言,分为三种缓冲区:

全缓存、行缓存、不缓存

2.全缓存:对应的是用户打开的文件指针:fp 其大小为4096字节

行缓存:对应的是stdin和stdout,其大小为1024字节

无缓冲:对应的是stderr,其大小为0字节

3.缓冲区的刷新时机

1、行缓存

1、遇到\n会刷新

2、当使用fflush刷新时,会刷新缓冲区

3、当程序结束时会刷新缓冲区

4、当使用exit退出进程时,会刷新标准io缓冲区

5、当输入输出发生切换时会刷新缓冲区

6、当缓冲区满了后,再向缓冲区中放数据时,会刷新该缓冲区

2、全缓存

1、当使用fflush刷新时,会刷新缓冲区

2、当程序结束时会刷新缓冲区

3、当使用exit退出进程时,会刷新标准io缓冲区

4、当输入输出发生切换时会刷新缓冲区

5、当缓冲区满了后,再向缓冲区中放数据时,会刷新该缓冲区

3、没有条件,放入立即刷新

有关错误码的问题

1.错误码是调用内核提供的函数时,如果调用出错,那么内核空间会向用户空间反馈一个错误信息

2.错误信息千奇百怪,并且是字符串内容,为了方便起见,给这些错误信息,进行编号

3.如果,内核空间函数调用出问题时,只需要反馈错误编号即可,这个错误编号就叫做错误码

4.常见错误码:可以通过指令 vi -t EIO 查看

文件IO:

文件IO是指用户直接调用内核提供的函数来进行IO操作,但是标准IO使用的是文件指针完成,文件IO使用的是文件描述符来实现

文件描述符

1.文件描述符是内核用来跟外部文件设备操作的一个非负整数

2.每一个文件描述符对应一个操作的文件

3.当一个程序启动后,系统默认打开三个特殊的文件描述符,分别是0号(标准输入stdin)、1号(标准输出)和2号(标准出错)

4.文件描述符的分配原则是:最小未使用原则

5.默认情况下,一个进程能够打开的文件描述符的个数为1024个,也就是0--1023

打开文件open

int open(const char *pathname, int flags);

int open(const char *pathname, int flags, mode_t mode);

功能:使用系统调用,打开给定pathname对应的文件,并返回该文件对应的文件描述符

参数1:要被打开的文件

参数2:打开模式

1、必须包含以下三个中的一个

O_RDONLY: 只读的形式打开文件

O_WRONLY:只写的形式打开文件

O_RDWR:读写的形式打开文件

2、下面的可以包含也可以不包含,根据需要而定,所有标识通过位或连接

O_CREAT:如果文件不存在,则创建文件,注意,如果参数2中包含该标识, 则必须提供参数3,为文件的操作权限

O_TRUNC:清空文件内容

O_APPEND:追加形式

O_EXCL:确保创建新文件成功,如果文件已经存在,则报错,错误码为EEXIST

参数3:文件操作权限。注意:最终的文件权限,是由给定的权限跟默认掩码取反后取位与运算得到

运算:mode & (~umask) umak取决于终端

一般情况下:文件夹的权限最大为:0775 普通文件的权限:0664

返回值:成功返回打开的文件对应的文件描述符(最小未分配原则),失败返回-1并置位错误码

标准IO打开文件模式对应的操作位

关闭文件close

int close(int fd);

功能:关闭指定的文件描述符

参数:文件描述符

返回值:成功返回0,失败返回-1并置位错误码

数据读写(read、write)

ssize_t read(int fd, void *buf, size_t count);

功能:从fd文件描述符中读取count个字节的数据,并存放到buf指向的容器中

参数1:文件描述符

参数2:存放数据的容器起始地址

参数3:要读取数据的大小

返回值:成功返回读取的字节个数,失败返回-1并置位错误码

ssize_t write(int fd, const void *buf, size_t count);

功能:向fd文件描述符标识的文件中写入以buf作为起始地址的count个数据

参数1:文件描述符

参数2:要写入数据的容器起始地址

参数3:要写入数据的大小

返回值:成功返回写入的字节个数,失败返回-1并置位错误码

光标偏移(lseek)

off_t lseek(int fd, off_t offset, int whence);

功能:偏移fd文件描述符的光标

参数1:文件描述符

参数2:偏移量(以字节为单位)

>0:表示从给定的基准向后偏移

=0:表示在基准处不偏移

<0:从基准处向前偏移

参数3:基准

SEEK_SET:文件开始位置

SEEK_CUR:光标当前位置

SEEK_END:文件结尾位置

返回值:成功返回光标当前位置,失败返回(off_t)-1并置位错误码


作业:

1> 使用fread、fwrite实现两个文件的拷贝

程序源码:

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

int main(int argc, const char *argv[])

{

FILE *fp=NULL;

FILE *fp1=NULL;

//从文件中读取数据

if((fp = fopen("./wcg.txt", "r")) == NULL)

{

printf("文件打开失败\n");

return -1;

}

if((fp1 = fopen("./wcgcope.txt", "w")) == NULL)

{

printf("文件打开失败\n");

return -1;

}

//将文件中的数据读取出来

char buf[128] = "";

while(1)

{

int res = fread(buf, 1, sizeof(buf), fp);

if(res < 128)

{

//判断是因为文件结束还是因为错误

if(feof(fp))

{

//printf("buf=%s\n", buf);

//将读取的数据全部写到新的文件中

fwrite(buf, res, 1, fp1);

break; //因为文件结束

}

if(ferror(fp))

{

printf("fread操作失败\n");

return -1;

}

}

//将读取的数据写到新的文件中

fwrite(buf, res, 1, fp1);

}

//关闭文件

fclose(fp);

fclose(fp1);

return 0;

}

2> 使用fread、fwrite实现将一个文件中的所有数字写入到另一个新文件中

程序源码:

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

//定义函数用于筛选数字

void num(char *p,char *q,int len)

{

int j=0;

for(int i=0;i<len;i++)

{

if(p[i]>='0'&&p[i]<='9')

{

q[j++]=p[i];

}

}

q[j]='\0';

}

int main(int argc, const char *argv[])

{

FILE *fp=NULL;

FILE *fp1=NULL;

//从文件中读取数据

if((fp = fopen("./wcg.txt", "r")) == NULL)

{

printf("文件打开失败\n");

return -1;

}

if((fp1 = fopen("./wcgcope1.txt", "w")) == NULL)

{

printf("文件打开失败\n");

return -1;

}

//将文件中的数据读取出来

char buf[128] = "";

while(1)

{

char arr[128]="";

int res = fread(buf, 1, sizeof(buf), fp);

if(res < 128)

{

//判断是因为文件结束还是因为错误

if(feof(fp))

{

//将读取的数据全部写到新的文件中

num(buf,arr,res);

fwrite(arr,1,strlen(arr),fp1);

break; //因为文件结束

}

if(ferror(fp))

{

printf("fread操作失败\n");

return -1;

}

}

//将读取的数据写到新的文件中

num(buf,arr,res);

fwrite(arr,1,strlen(arr),fp1);

}

//关闭文件

fclose(fp);

fclose(fp1);

return 0;

}

3> 使用文件IO完成两个文件的拷贝

程序源码:

#include <25072head.h>

int main(int argc, const char *argv[])

{

//1、创建并打开一个文件

int fd = -1;

if((fd = open("./tt.txt", O_RDWR|O_CREAT|O_TRUNC, 0664)) == -1)

{

perror("open error");

return -1;

}

int fd1=-1;

if((fd1 = open("./ttcope.txt", O_RDWR|O_CREAT|O_TRUNC, 0664)) == -1)

{

perror("open error");

return -1;

}

printf("fd = %d\n", fd);

//向文件中写入数据

char buf[128] = "";

while(1)

{

//从终端获取数据

int res = read(0, buf, sizeof(buf));

if(res == 1)

{

break;

}

//将数据写入到fd指向的文件中

write(fd, buf, res);

}

//从文件中读取数据

lseek(fd,0,SEEK_SET);

char rbuf[128] = "";

int res = read(fd, rbuf, sizeof(rbuf)); //从文件中读数据

//将数据写到终端上

write(fd1, rbuf, res);

//关闭文件

close(fd);

return 0;

}

4> 自己总结标准IO和文件IO的区别与联系

标准IO:代码和程序员之间的数据交互

文件IO:代码和文件系统之间的数据交互

1.文件IO没有缓冲区,标准IO函数存在缓冲区

2.标准IO函数的读取速度快于文件IO函数

3,标准IO函数本质上就是文件IO的二次封装,标准IO=文件IO+缓冲区

4.文件IO可以直接和内核交互,标准IO不可以直接和内核交互,标准IO函数只可以访问普通文件,但是文件IO函数可以访问任意的特殊文件(管道,套接字)

5.文件IO属于系统文件,依赖于操作系统,可以移植性差

6.标准IO函数属于库文件,可以在不同的操作系统中使用,可移植性强

7.文件IO遵循POIX标准,标准IO函数满足ANSI标准

8.文件IO函数操作文件需要借助于文件描述符

9.标准IO函数操作文件需要借助于流指针

5> 思维导图

6> 牛客网刷题 >= 26

相关推荐
Nuyoah11klay2 天前
华清远见25072班I/O学习day1
c语言·i/o
颜淡慕潇3 个月前
什么是异步 I/O?深入解析从基础到实践
i/o·异步i/o
G皮T3 个月前
【Python Cookbook】文件与 IO(二)
python·i/o·io·文件·gzip·stringio·bytesio
G皮T3 个月前
【Python Cookbook】文件与 IO(一)
python·i/o·文件·file
青草地溪水旁7 个月前
I/O 事件的概念
linux·i/o
和舒貌7 个月前
深入理解同步与异步I/O:从原理到实战
c++·windows·i/o·信息与通信
汤姆和佩琦8 个月前
24-12-28-pytorch深度学习中音频I/O 中遇到的问题汇总
人工智能·pytorch·python·深度学习·音视频·i/o
Winston Wood10 个月前
Android中的epoll机制
android·性能优化·i/o·epoll
程序研1 年前
JAVA中的BufferedOutputStream
java·开发语言·后端·i/o