1.标准IO
1.1文件基础
(1)文件类型:
常规文件 r
目录文件 d
字符块设备文件 c
块设备文件 b
管道文件 p
套接字文件 s
符号链接文件 l
(2)系统调用和C库函数
最初的用户应用代码直接操作内核,这样势必会导致内核处理的数据庞大并且很有可能会破坏内核中一些重要的文件或者数据;所以在之后,应用代码通过C库提供的API进行内核之上的系统调用,系统调用再对内核进行应用代码相关申请的任务进行处理。
(3)标准IO
标准IO由ANSI C标准定义,主流的操作系统上都实现了C库,标准IO通过缓冲机制减少了系统调用,实现更高的效率。
1.2标准I/O——流
(1)FILE:
标准IO用一个结构体类型来存放打开的文件的相关信息
标准IO的所有操作都是围绕FILE来进行
(2)流(stream)
FILE又被称作流
文本流和二进制流
(3)区分windows和linux下面文本流和二进制流的换行符区别
windows
二进制流:换行符——>’\n’
文本流:换行符——>’\r’ ‘\n’
linux
换行符——>’\n’
(4)流的缓冲类型
全缓冲:当流的缓冲区无数据或无空间时才执行实际IO操作
行缓冲:当在输入和输出中遇到换行符(‘\n’)时,进行IO操作
当流和终端关联的时候,典型的行缓冲
无缓冲:数据直接写入文件,流不进行缓冲
(5)stdin、stdout、stderr
标准IO预定义了三个流,程序运行的时候自动打开
标准输入流 0 STDIN_FILENO stdin
标准输出流 1 STDOUT_FILENO stdout
标准错误流 2 STDERR_FILENO stderr
2.流的操作
2.1流的打开和关闭
2.1.1流的打开
(1)打开一个标准IO流:
FILE *fopen(const char *path, const char *mode)
成功打开返回流指针;出错时返回NULL
(2)mode参数:
r、rb 只读方式打开文件,文件必须存在
r+、r+b 读写方式打开文件,文件必须存在
w、wb 只写方式打开文件,若文件存在则先清零。若文件不存在,则新建。
w+、w+b 读写方式打开文件,若文件存在则先清零。若文件不存在,则新建。
a、ab 只写方式打开文件,若文件不存在则创建;文件存在,则向文件末尾追加要写入数据
a+、a+b 读写方式打开文件,同a
(3)fopen创建的文件权限
fopen()创建的文件访问权限是0666(rw-rw-rw-)
linux系统中umask设定会影像文件的访问权限,其规则是:(0666)&~umask
root用户是022 普通用户是002
ps:如果要让fopen()创建的文件访问权限不受umask影响,该如何设置umask值?
(4)处理错误信息
extern int errno;
void perror(const char *s);
char *strerror(int errno);
errno存放错误号,由系统生成
perror先输出字符串s,再输出错误号对应的错误信息
strerror根据错误号返回对应的错误信息
头文件<errno.h>
2.1.2流的关闭
(1)关闭一个标准IO流:
int fclose(FILE *stream);
fclose()调用成功返回0,失败返回EOF,并设置errno
流关闭时自动刷新缓冲区中的数据并释放缓冲区
当一个程序正常终止时,所有打开的流都会被关闭
流一旦关闭后就不能执行任何操作
ps:测试程序中能够打开文件或者流的个数?
2.2读写流
2.2.1读取字符
(1)读取一个字符:
int fgetc(FILE *stream);
int getc(FILE *stream);
int getchar(void);
成功时返回读取的字符;若到文件末尾或者出错时返回EOF
getchar()等同于fgetc(stdin)
getc和fgetc区别是一个是宏一个是函数
(2)写入一个字符:
int fputc(int c, FILE *stream);
int putc(intc, FILE *stream);
int putchar(int c);
成功时返回写入的字符;出错时返回EOF
putchar©等同于fputc(c, stdout)
ps:利用fgetc和fputc实现文件复制,命令行参数传递源文件和目标文件
2.2.2读取行
(1)读取一行数据:
char *gets(char *s);
char *fgets(char *s, int size, FILE *stream);
成功时返回s,到文件末尾或出错时返回NULL
gets不推荐使用,容易造成缓冲区溢出
遇到’\n’或已输入size-1个字符时返回,总是包含’\0’
(2)写入一行数据:
int puts(const char *s);
int fputc(const char *s, FILE *stream);
成功时返回写入的字符个数,出错时返回EOF
puts将缓冲区s中的字符串写入到stout,并追加’\n’
fputs将缓冲区s中的字符串写入到stream,不追加’\n’
ps:统计一个文本文件有多少行
2.2.3读取对象
(1)读取/写入若干个对象:
size_t fread(void *ptr, size_t size, size_t n,FILE *fp);
size_t fwrite(const void *ptr, size_t size, size_t n, FILE *fp);
成功时返回读取或者写入的对象的个数,出错时返回EOF
既可以读写文本文件,也可以读写数据文件
(2)格式化输入输出:
int fprintf(FILE *stream, const char *format, …); (写入)
int sprintf(char *str, const char *format, …);(读出)
int printf(const char *fmt, …);
成功时返回输出字符的个数;出错时返回EOF
int fscanf(FILE *stream, const char *format, …);
int sscanf(const char *str, const char *format, …);
ps:利用fread和fwrite实现文件复制?
2.3流的刷新和定位
2.3.1流的刷新
(1)刷新流:
int fflush(FILE *fp);
成功时返回0;出错时返回EOF
将缓冲区中的数据写入实际文件
linux下只能刷新输出缓冲流,输入缓冲区丢弃
2.3.2流的定位
(1)定位流:
long ftell(FILE *stream);
long fseek(FILE *stream, long offset, int whence);
void rewind(FILE *stream);
ftell()成功时返回流的当前读写位置,出错时返回EOF
fseek()定位一个流,成功时返回0,出错时返回EOF
whence参数:SEEK_SET/SEEK_CUR/SEEK_END
offset参数:偏移量,可正可负
rewind()将流定位到文件开始位置
读写流时,当前读写位置自动后移
2.3.3判断流是否出错
*(1) int ferror(FILE stream);
*(2) int feof(FILE stream);
ferror()返回1表示流出错,否则返回0
feof()返回1表示文件已经到末尾,否则返回0