什么是io
io接口,又称为输入输出接口,是信息处理系统与外部世界之间的通信,输入时系统接受的信号或者数据,输出就是从其发送的信号或数据。
input:通过终端向程序中输入数据;
output:程序的结果通过终端(显示屏等)输出;
io的种类
文件io->系统调用
系统调用就是操作系统提给应用程序(编程人员)使用的接口,可以理解其为一种可供应用程序调用的 '特殊函数',应用程序可以发出系统调用来获操作服务。从要从用户空间到内核空间就发生一次系统调用。
系统调用的特点:1.系统调用的接口不同意,依赖于内核,不保证移植性
2.系统调用没有缓冲区,效率比较低。
标准io->库函数
库函数(AANSI C)是由文件io封装而来的,通过缓冲区机制减少系统调用,
库函数=系统调用+缓冲区;库函数具有缓冲区,所以效率比系统调用更高。
缓冲区
缓冲区:就是暂存输入(输出)的数据,等待缓冲区刷新,在一同输入(输出)到内核空间。
缓冲区的种类和大小:
全缓存:和文件相关的缓冲区就是全缓存(4096字节)4K;例如;fd;
行缓存:和终端相关的缓冲区就是行缓存 (1024字节)1K;例如:stdin 、stdout
不缓存:标准出错没有缓冲区 0 ;例如:stderr(标准出错)
缓冲区的刷新时机:
行缓存的刷新时机:
1.遇到换行符(\n)
2.输入输出切换时
3.程序运行结束时
4.关闭文件
5.缓存区存储满时
6.使用fflush主动刷新缓冲区
全缓存的刷新时机:
1.输入输出切换时
2.程序运行结束时
3.关闭文件
4.缓存区存储满时
5.使用fflush主动刷新缓冲区
标准io的API函数
在介绍标准io的API函数之前,先说一下FILE类型,FILE类型本质是一个结构体,这个结构体中记录所i有关于文件的信息,以后对文件的操作通过FILE*来完成。
在打开文件的时候,会返回一个FILE*的指针(文明)
FILE *fp 是声明,声明fp是指针,用来指向FILE类型的对象。
fopen ->使用标准io打开文件,
#include <stdio.h>
FILE *fopen(const char *pathname, const char *mode);
功能:使用标准IO打开文件
参数:
@pathname: 路径/文件名 "./hello.txt"
@mode:打开文件的方式 "r" "r+"
r:以只读的方式打开文件,将文件中的光标定位在文件的开头
r+:以读写的方式打开文件,将文件中的光标定位在文件的开头
w:以只写的方式打开文件,如果文件不存在就创建文件,如果文件存在就清空,将光标定位在开头
w+:以读写的方式打开文件,如果文件不存在就创建文件,如果文件存在就清空,将光标定位在开头
a:以追加(结尾写)的方式打开文件,如果文件不存在就创建文件,将光标定位在文件的结尾
a+:以读和追加(结尾写)的方式打开文件,如果文件不存在就创建文件,如果读从开头读,写在文件的结尾写
返回值:成功返回文件指针,失败返回NULL,置位错误码
fopen实例
#include <stdio.h>
int main(int magc,const char*argv[])
{
//定义文件指针
FILE* fd;
//以只读方式打开文件
fd = fopen("./hello.txt","r");
if(NULL == fd)
{
printf("fopen error");
return -1;
}
return 0;
}
fclose->关闭文件
int fclose(FILE *stream);
功能:关闭文件
参数:
&stream:文件指针
返回值:
成功返回0,失败返回(end of file),并置位错误码。
fclose实例
#include <stdio.h>
int main(int magv,const char*argv[])
{
//定义文件指针
FILE * fd;
//以只写方式打开文件
fd = fopen("./hello.txt","w")
if(NULL == fd)
{
printf("fopen error");
}
//关闭文件
fclose(fd);
return 0;
}
关于错误码的问题
在文件io和标准相关接口被调用时,如果出错了,操作系统会给程序返回错误码。
我们在应用层使用fope打开文件的时候,底层的sys——open函数会被调用,如果fopen打开文件失败了,就会给上上层返回错误码,并将错误码的值赋值给errno变量,同时也会使fopen的返回值置为NULL。系统中一共有4K个错误码。
errno->错误码变量
#include <stdio.h
#include <errno.h>
//errno的头文件为<errno.h>
int main(int argc,const char* argv[])
{
//FILE *fd;
if(NULL == (fp=fopen("./hello.txt","w")
{
printf("fopen file error");
//打印错误码
printf("errno = %d\n",errno);
return -1;
}
return 0;
}
strerror->将错误信息码转为错位信息的函数strerror
#include <string.h>
char*strerror(int errnum);
功能:将错误码转为错误码对应错误信息
参数:
@errnum:错误码(errno)
返回值:错误信息的字符串首地址
strerror实例
#include <stdio.h>
#incluse <errno.h>
#include <string.h>
int main(int argc,const char* argv[])
{
FILE *fd;
if(NULL == (fd = fopen("./hello.txt","a"))) //以追加方式打开文件
{
printf("fopen file error");
printf("errno = %d\n",errno);
//打印错误信息
printf("strerror = %s\n",strerror(errno));
return -1;
}
return 0;
}
perror->直接将将错误信息打印到终端(常用)
void perror("const char *s")
功能:将错误信息打印到终端
参数:
@s:附加信息字符串
返回值:无
perror实例
#include <stdio.h>
int main(int argc, const char* argv[])
{
FILE* fp;
if ((fp = fopen("./hello.txt", "r")) == NULL)
{
//打印错误信息到终端
perror("fopen file error");
return -1;
}
return 0;
}
fgetc/fputc-> 像文件中读取/写入一个字符
#include <stdio.h>
//fputc像文件中写入字符串
int fputc(int c, FILE *stream);
功能:向文件中写入字符
参数:
@c:字符的ascii
@stream:文件指针
返回值:成功返回字符ascii值,失败返回EOF(-1)
//fgetc从文件中读取一个字符
int fgetc(FILE *stream);
功能:从文件中读取字符
参数:
@stream:文件指针
返回值:成功读取到的字符的ascii,读取到文件结尾或者出错,返回EOF(-1)
fgetc/fputc实例(使用fgetc/fputc使用文件拷贝)
#include <stdio.h>
int main(int argc, const char* argv[])
{
FILE *fp1, *fp2;
int ch;
// 1.校验命令行参数的个数
if (argc != 3) {
printf("input error,try again\n");
printf("usage: ./a.out srcfile destfile\n");
return -1;
}
// 2.只读方式打开源文件,以只写方式打开目标文件
if ((fp1 = fopen(argv[1], "r")) == NULL) {
perror("fopen src error");
return -1;
}
if ((fp2 = fopen(argv[2], "w")) == NULL) {
perror("fopen dest error");
return -1;
}
// 3.循环拷贝
while ((ch = fgetc(fp1)) != EOF) {
fputc(ch,fp2);
}
// 4.关闭文件
fclose(fp1);
fclose(fp2);
return 0;
fgets/fputs->向对应的文件中获取/写入字符串
//fgts向对应文件中获取size-1个字符,获取的字符串自动加上'\0'
char *fgets(char *s, int size, FILE *stream);
功能:从stream对应的文件中最多读取size-1个字符到s中
读停止:当遇到EOF或者换行符时候会停止,如果是换行符停止的,它会将换换行符存储到s中
s的结束:在s存储的最后一个字符之后通过添加'\0'的形式表示结束
s=0123456789'\n''\0' size=100 文件第一行10个字符
s=01234'\0' size=6 文件第一行10个字符
参数:
@s:用于存储读取到的字符串的首地址
@size:读取字符串中字符的个数
@stream:文件指针
返回值:成功返回s,失败返回NULL
//fputs向对应文件中写入字符串
int fputs(const char *s, FILE *stream);
功能:将s中的内容写入到stream对应的文件中(不包含'\0')
参数:
@s:被写字符串的首地址
@stream:文件指针
返回值:成功返回大于0的值,失败返回EOF
fgets/fputs实例(使用fgets/fputs实现文件拷贝)
#include <stdio.h>
int main(int argc, const char* argv[])
{
FILE *fp1, *fp2;
char buf[20] = {0};
// 1.校验命令行参数的个数
if (argc != 3) {
fputs("input error,try again\n",stderr);
fputs("usage: ./a.out srcfile destfile\n",stderr);
return -1;
}
// 2.只读方式打开源文件,以只写方式打开目标文件
if ((fp1 = fopen(argv[1], "r")) == NULL) {
perror("fopen src error");
return -1;
}
if ((fp2 = fopen(argv[2], "w")) == NULL) {
perror("fopen dest error");
return -1;
}
// 3.循环拷贝 fgets成功返回buf(非0就会进入while),
//失败返回NULL(void *)0,假退出循环
while (fgets(buf,sizeof(buf),fp1)) {
fputs(buf,fp2);
}
// 4.关闭文件
fclose(fp1);
fclose(fp2);
return 0;
}