IO学习
1、什么是IO:
I:input
O:output
输入:从键盘将数据输入到内存中
输出:从内存将数据拷贝到显示屏上
对IO更深层次的理解:
Linux下一切皆文件
输入:从文件将数据输入到内存中
输出:从内存将数据拷贝到文件中
2、标准IO
标准IO由ANSI C标准说明
(1)可以跨平台,既可以在windows下使用,又可以在Linux上使用
(2)库函数
(3)有缓冲区
(4)通过FILE指针操作,文件流指针来进行操作
3、相关概念
3.1系统调用
系统:操作系统
调用:调用函数
系统调用:调用操作系统提供的函数
官方系统调用:操作系统提供给应用程序的接口(函数)
3.2缓冲区
作用:减少系统调用次数
全缓存:当缓冲区满、程序结束、强制刷新缓冲区
行缓存:当缓冲区满、程序运行结束、强制刷新缓冲区、遇到换行符时会刷新缓冲区
程序结束时
缓冲区没有满
强制刷新缓冲区
行缓存遇到换行符
不缓存:没有缓冲区直接输出
程序运行起来之后,会默认打开桑格文件,标准输入、标准输出、标准出错对应的流指针为:stdin
、stdout
、stderr
3.3文件
一组相关数据的有序集合
文件名:这组集合的名称
文件类型:
-
:普通文件:ASCII文件和二进制文件
d
:目录文件
b
:块设备
c
:字符设备文件
l
:字符设备文件
p
:管道文件
s
:套接字文件(socket)
3.4流和FILE指针
3.4.1:流(stream):字节的进进出出
3.4.2:流的分类:
文本流:数字2001对应的文本流‘2’‘0’‘0’‘1’(50 48 48 49)
3.4.3:FILE指针:每个被使用的文件都会在内存中开辟 一个空间,这些信息包保存在结构体中,取名为FILE
注意:标准IO中所有的操作都是围绕流来进行的,流用FILE *来描述
4、标准IO相关函数
4.1、打开文件(文件操作步骤1):
FILE *fopen(char *pathname, const char *mode);
函数功能:打开文件
参数1:要打开文件的路径
参数2:打开的方式
`r`:以只读的方式打开文件,文件不存在则出错
`r+`:以可读可写的方式打开文件,文件不存在则出错
`w`:以只写的方式打开文件,文件不存在则新建,文件存在则清空文件中的内容
`w+`:以可读可写的方式打开文件,文件不存在则新建,文件存在则清空文件中的内容
a
:以追加的方式打开只写文件,文件不存在则新建,文件存在则追加在文件的末尾
a+
:以追加的方式打开只写文件,文件不存在则新建,文件存在则追加在文件的末尾,返回值:成功返回文件流指针,失败返回NULL
4.2、操作文件(读/写)(文件操作步骤2):
文件操作分为:按字符读写、按行读写、按块读写
4.2.1按字符读写
getchar()
、putchar()
:只能从键盘输入、输出
fgetc()
、fputc()
:既能从键盘输入、输出,也可以从文件中输入、输出
int fgetc(FILE *stream);
函数功能:从指定的流中读取一个字符
参数:fopen的返回值,已经打开的文件流指针
返回值:才成功返回督导的ASCII码值,失败OR读到文件末尾返回EOF

功能:向指定的流中输出一个字符
参数1:要输出的字符
参数2:fopen的返回值,已经打开的文件流指针
返回值:成功返回写入的ASCII码值,失败返回-1
案例:读取一个文件,将文件的内容输出到标准输出上
案例:实现拷贝
`int feof(FILE *stream);`
函数功能:判断文件是否到达文件末尾
参数:文件流指针
返回值:非零表示到达文件末尾,为零表示未到达文件末尾
注意:feof即可判断到达文本文件的末尾,也可判断是否到达二进制文本文件的末尾
4.2.2按行读写
gets()
、puts()
fgets()
、fputs()
char *fgets(char *s,int size,FILE *stream)
函数功能:从指定的流中读取一串字符
参数1:读到的内容的空间的首地址
参数2:读到的空间的大小
参数3:文件流指针
返回值:成功返回读到的内容空间的首地址,失败或者读到到文件末尾返回
NULL
总结:
(1)fgets读取内容时会将换行符也读入
(2)fgets最多读取到size-1
(3)fgets比gets更安全,最多读取size-1个字符
(4)fgets读取时会将换行符
int fputs(const char *s, FILE *stream);
函数功能:向指定的字符串输出一串字符
参数1:要输出的字符串的首地址
参数2:文件流指针
返回值:成功返回非负的整数,失败返回-1
4.2.3按块读写
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
//解释:The function fread() reads nmemb items of data,
// each size bytes long, from the stream pointed to by
// stream, storing them at the location given by ptr.
功能:按块读写
参数1:读到内容空间的首地址
参数2:每次读取的字节数 //size_t代表无符号整型
参数3:读取次数
参数4:要操作的文件流指针
返回值:成功返回读到的块数,失败返回-1
//假设读100个字节,每个块的大小为20,块的个数5
一般情况下:将size设为1, nmemb要读的大小,返回值就是实际读到的字节数
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
功能:按块写数据
参数1:要写的内容空间的首地址
参数2:块的大小
参数3:块的个数
参数4:文件流指针
返回值:成功返回写入的块数,失败返回-1
long ftell(FILE *stream);
函数功能:获取当前文件的位置
参数:文件流指针
返回值:成功返回当前文件的位置,失败返回-1
int fseek(FILE *stream, long offset, int whence);
功能:获取流的位置
参数1:文件流指针
参数2:偏移量
参数3:偏移位置
SEEk_SET:文件开头
SEEK_CUR:当前位置
SEEK_END:文件末尾
4.3、关闭文件:
int fclose(FILE *stream);
参数:fclose的返回值,已经打开的文件流指针
返回值:成功返回0;失败返回EOF(-1)
注意:EOF(end of file)只能判断是否到达文件的末尾,不能判断到达二进制文件
5文件IO
5.1、文件IO
(1)文件描述符(非负整数)
(2)无缓冲机制
(3)系统调用
(4)一般用于设备文件的操作
5.2、文件IO的相关函数
操作文件的步骤
(1)打开文件
(2)操作文件
(3)关闭文件
5.2.1打开文件
//头文件:
#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);
参数1
:文件路径
参数2
:打开方式(flags)
以下参数,必选其一
O_RDONLY
:只读
O_WRONLY
:只写
O_RDWR
:可读可写
其余的和上面的进行或运算|
O_CREAT
:如果文件不存在,则新建(必须使用第三个参数)
O_EXCL
:如果使用O_CREAT时文件存在,则返回错误消息。 这一参数可测试文件是否存在。
O_NOCTTY
:使用该参数时,若打开的是终端文件,那么该终端不会成为当前进程的控制终端
O_TRUNC
:如文件已经存在,那么打开文件时先删除文件中原有数据。
O_APPEND
:以追加的方式打开文件,追加在文件的末尾(文件读写位置自动指向文件的末尾)
参数3
:(mode)权限(一般用8进制数表示)
返回值
:成功返回文件描述符,失败返回-1
2.2关闭文件
//头文件:
#include <unistd.h>
int close(int fd);
参数:open的文件描述符文件描述符
返回值:成功返回0,失败返回-1
文件掩码
案例:测试OS最多能打开多少个文件
int sprintf(char *str, const char *format, ...);
程序运行起来之后,三个文件已经默认打开:
标准输入
标准输出
标准出错
2.3操作文件
头文件:
#include <unistd.h>
函数原型:
ssize_t read(int fd, void *buf, size_t count);
参数1:文件描述符,open函数的返回值
参数2:读到的内容空间的首地址
参数3:要读的大小
返回值:成功返回读到的字节数,0表示文件末尾,失回-1败返
ssize_t write(int fd, const void *buf, size_t count);
参数1:文件描述符,open的返回值
参数2:写的内存空间的首地址
参数3:要写的大小
返回值:成功返回写入的字节数,0表示未写入,失败返回-1
案例:实现文件的拷贝
2.4 其它函数
void *memset(void *s, int c, size_t n);
参数1:要清零的数组或结构体的首地址
参数2:c的范围是0~255
参数3:要清零的数组或结构体的空间大小
返回值: 该值返回一个指向存储区首地址的void *s类型的指针。
注意:成功memset的返回值是数组/结构体的首地址
头文件:
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
参数1:文件描述符
参数2:偏移量
参数3:偏移的位置(SEEK_SET
:文件开头、SEEK_CUR
:当前位置、SEEK_END
:文件末尾)
对同一个文件进行读/写时必须是O_RDWR,要不然读到的就是乱码
什么是文件描述符:文件描述符是一个非负整数,它是一个索引值,并指向在内核 中 每个进程打开文件的记录表。当打开一个现存文件或创建一个新文件时,内核就向进程返回一个文件描述符;读写文件时,需要把文件描述符作为参数传递给相应的函数。通常一个进程启动时们都会打开3个流,标准输入(STDIN_FILENO)、标准输出(STDOUT_FILENO)和标准错误(STDERR_FILENO),这三个流分别对应文件描述符0、1和2.