目录
3.最早接触的IO
#include <stdio.h>
stdio:标准的IO(Input/output)
那些是标准IO的接口:printf/scanf
4.IO的种类
标准IO:库函数
文件IO:系统调用
5.什么是库函数,什么是系统调用?
系统调用:从用户空间进入内核空间的一次过程就是一次系统调用。
系统调用没有缓冲区,系统调用的效率比较低。
库函数:库函数=系统调用+缓冲区,库函数有缓冲区,效率比较高。可移植性比较强(平台通用性强)
6.常见的标准IO和文件IO有哪些?
标准IO:printf、scanf、fopen、fclose、fread、fwrite、fputc、fgetc、fputs、fgets等
文件IO:open、read、write、close等
7标准IO
7.1什么是FILE
FILE是一个结构体,这个结构体用来记录打开文件的所有的信息。
在使用fopen打开一次文件就会产生一个FILE结构体。以后对文件
的操作都通过文件指针完成。
typedef struct _IO_FILE FILE;
struct _IO_FILE {
char* _IO_buf_base; //缓冲器的起始地址
char* _IO_buf_end; //缓冲区的结束地址
...
}
三个特殊的FILE指针:(在一个正在执行的程序中,默认这个三个指针都已经可以使用)
stdin :标准输入
stdout :标准输出
stderr :标准错误
7.2fopen函数的使用
7.2.1fopen函数接口讲解
man man
2 系统调用(内核提供的函数)
3 库调用(程序库中的函数)
man 3 fopen
#include <stdio.h>
FILE *fopen(const char *pathname, const char *mode);
功能:使用标准IO的接口打开文件
参数:
@pathname:想要打开的文件的路径及名字 "./hello.txt"
@mode:打开文件的方式 "r+" "r"
r 以只读的方式打开文件,将光标定位到文件的开头
r+ 以读写的方式打开文件,将光标定位到文件的开头
w 以只写的方式打开文件,如果文件不存在就创建文件,如果文件存在就清空,将光标定位到开头
w+ 以读写的方式打开文件,如果文件不存在就创建文件,如果文件存在就清空,将光标定位到开头
a 以追加的方式打开文件,如果文件不存在就创建文件,如果文件存在将光标定位到文件的结尾
a+ 以读和追加的方式打开文件,如果文件不存在就创建文件,如果文件存在读的时候光标在开头
写的时候光标在结尾
返回值:成功返回FILE指针,失败返回NULL,置位错误码
7.2.2fopen函数的使用
#include <stdio.h>
int main(int argc,const char * argv[])
{
FILE *fp;
//以只写方式打开文件,如果文件不存在就创建文件,如果文件存在就清空
if((fp = fopen("./hello.txt","w"))==NULL){
printf("fopen file error\n");
return -1;
}
return 0;
}
#include <stdio.h>
int main(int argc,const char * argv[])
{
FILE *fp;
//只读的方式打开文件,如果文件不存在,读失败,报错返回
if((fp = fopen("./hello.txt","r"))==NULL){
printf("fopen file error\n");
return -1;
}
return 0;
}
7.3fclose函数的使用
7.3.1fclose函数的功能介绍
int fclose(FILE *stream);
功能:关闭文件
参数:
@stream:文件指针
返回值:成功返回0,失败返回EOF(-1),置位错误码
7.3.2fclose函数的使用
#include <stdio.h>
int main(int argc, const char* argv[])
{
FILE* fp;
if ((fp = fopen("./hello.txt", "w")) == NULL) {
printf("fopen file error\n");
return -1;
}
//编译器自动解析
//__FILE__:文件的名字
//__func__:函数名
//__LINE__:打开语句对应的行号
printf("%s:%s:%d\n", __FILE__, __func__, __LINE__);
//文件打开后只能被关闭一次,第二次关闭的时候报错
if (fclose(fp)) {
printf("fclose file error\n");
return -1;
}
//一个正在执行的程序中默认有三个文件指针可以使用
// stdin stdout stderr,如果关闭了stdout,此时
//标准输出就不能使用了
printf("111111111111111111111\n");
if (fclose(stdout)) {
printf("fclose file error\n");
return -1;
}
printf("22222222222222222222222\n");
return 0;
}
7.4关于系统错误码的问题
7.4.1系统错误码的简介
在linux内核中一共有4K个错误码,在linux内核中定义。
#include <stdio.h>
#include <errno.h>
int main(int argc,const char * argv[])
{
FILE *fp;
//只读的方式打开文件,如果文件不存在,读失败,报错返回
if((fp = fopen("./hello.txt","r"))==NULL){
//这里就能够打印出errno为2的错误,但是
//看到2之后并不知道是什么错误,
printf("errno = %d\n",errno);
printf("fopen file error\n");
return -1;
}
return 0;
}
7.4.2strerror函数的使用
#include <string.h>
char *strerror(int errnum);
功能:将错误码转化为错误信息
参数:
@errnum:错误
返回值:错误信息
#include <errno.h>
#include <stdio.h>
#include <string.h>
int main(int argc, const char* argv[])
{
FILE* fp;
//只读的方式打开文件,如果文件不存在,读失败,报错返回
if ((fp = fopen("./hello.txt", "r")) == NULL) {
//这里就能够打印出errno为2的错误,但是
//看到2之后并不知道是什么错误,
printf("errno = %d\n", errno);
//将错误码转化为错误信息
printf("%s\n",strerror(errno));
printf("fopen file error\n");
return -1;
}
return 0;
}
7.4.3perror函数的使用
#include <stdio.h>
void perror(const char *s);
功能:如果错误码置位了,打印错误信息
参数:
@s:附加的字符串
返回值:无
#include <stdio.h>
int main(int argc, const char* argv[])
{
FILE* fp;
// //只读的方式打开文件,如果文件不存在,读失败,报错返回
if ((fp = fopen("./hello.txt", "r")) == NULL) {
perror("fopen hello.txt error");
return -1;
}
return 0;
}
7.5fputc/fgetc函数的使用
7.5.1fputc/fgetc功能介绍
int fgetc(FILE *stream);
功能:从文件中读取一个字符到你的程序中(光标会自动向后移动一个字符)
参数:
@stream:文件指针
返回值:成功返回字符的ascii的值,失败返回EOF
int fputc(int c, FILE *stream);
功能:向文件中写入一个字符 (光标会自动向后移动一个字符)
参数:
@c:被写入的字符
@stream:文件
返回值:成功返回写入字符的ascii的值,失败返回EOF
7.5.2fputc函数的实例
#include <stdio.h>
int main(int argc, const char* argv[])
{
FILE* fp;
// 1.打开文件
if ((fp = fopen("./hello.txt", "w")) == NULL) {
perror("fopen error");
return -1;
}
// 2.调用fputc向文件中写入字符
fputc('h', fp); //向fp对应的文件中写入h字符
fputc('e', fp); //当上一句fputc执行完之后光标就会向后移动,e字符就在h之后
fputc('l', fp);
fputc('l', fp);
fputc('o', fp);
//3.关闭文件
fclose(fp);
return 0;
}
7.5.3fgetc函数的实例
#include <stdio.h>
int main(int argc,const char * argv[])
{
FILE *fp;
if((fp = fopen("./hello.txt","r"))==NULL){
perror("fopen hello.txt error");
return -1;
}
printf("%c",fgetc(fp)); //将fgetc读取到的字符显示到终端上,光标会向后移动
printf("%c",fgetc(fp));
printf("%c",fgetc(fp));
printf("%c",fgetc(fp));
putchar(10);
fclose(fp);
return 0;
}
7.5.4练习(文件的结尾是EOF)
1.使用fgetc统计文件的行号
./a.out filename
#include <stdio.h>
//./a.out filename
// argc:命令行参数的个数,(包含) argc=2
// argv:它是一个指针数组,数组中的成员是char *的指针
// argv[0] = "./a.out"
// argv[1] = "filename"
int main(int argc, const char* argv[])
{
FILE* fp;
char ch;
int line=0;
// 1.校验用户传递的参数是否正确
if (argc != 2) {
printf("input argumemt error,try again\n");
printf("usage: ./a.out filename\n");
return -1;
}
// 2.打开文件(只读)
if ((fp = fopen(argv[1], "r")) == NULL) {
printf("fopen file error");
return -1;
}
// 3.循环读取字符,直到EOF位置,判断是否等于'\n'
while ((ch = fgetc(fp)) != EOF) {
if(ch=='\n'){
line++;
}
}
//4.输出行号
printf("line = %d\n",line);
//5.关闭文件
fclose(fp);
return 0;
}
8.作业
使用fgetc/fputc实现文件的拷贝
./a.out srcfile destfile
#include <stdio.h>
int main(int argc, const char* argv[])
{
// 1.校验参数
if (argc != 3) {
printf("input error,try again\n");
printf("usage: ./a.out srcfile destfile\n");
return -1;
}
// 2.打开文件
FILE *sfp, *dfp;
if ((sfp = fopen(argv[1], "r")) == NULL) {
perror("fopen srcfile error\n");
return -1;
}
if ((dfp = fopen(argv[2], "w")) == NULL) {
perror("fopen destfile error\n");
return -1;
}
//3.循环拷贝
char ch;
while((ch = fgetc(sfp))!=EOF){
fputc(ch,dfp);
}
//4.关闭文件
fclose(sfp);
fclose(dfp);
return 0;
}