相关概念
1. **标准I/O的概念**:
- 标准I/O是由Dennis Ritchie在1975年为C语言设计的一套库,它是ANSI C标准的一部分。
- 标准I/O提供了一组函数,用于简化文件I/O操作,包括输入和输出。
2. **标准I/O的头文件**:
- `stdio.h`是标准I/O库的头文件,它包含了进行输入输出操作所需的函数声明。
3. **文件的概念和作用**:
- 在Linux操作系统中,一切都是文件,包括设备文件、普通文件等。
- 文件用于存储数据和指令。
4. **Linux中文件的类型**:
- Linux文件系统支持多种类型的文件,包括:
- 普通文件(-)
- 目录(d)
- 符号链接(l)
- 管道(p)
- 套接字(s)
- 字符设备文件(c)
- 块设备文件(b)
5. **标准I/O的缓存机制**:
- 标准I/O通常使用缓存机制来提高文件I/O的效率,减少系统调用的次数。
### 缓冲机制类型:
1. **行缓冲(Line Buffering)**:
- 主要用于终端(如控制台)的`stdout`输出。
- 缓冲区大小通常为1KB。
- 刷新条件:
- 遇到换行符`\n`时自动刷新。
- 缓冲区满时自动刷新。
- 程序结束时自动刷新。
- 通过`fflush(stdout);`手动刷新。2. **全缓冲(Full Buffering)**:
- 主要用于文件读写操作。
- 缓冲区大小通常为4KB(4096字节)。
- 刷新条件:
- 缓冲区满时自动刷新。
- 程序结束时自动刷新。
- 通过`fflush(fp);`手动刷新,其中`fp`是指向文件的指针。3. **无缓冲(Unbuffered)**:
- 主要用于错误信息的输出,如`stderr`。
- 不对数据进行缓存,直接输出。
- 通常用于紧急或错误信息的输出,以确保信息能够立即显示。### 缓冲区的刷新:
- **自动刷新**:在特定条件下(如行缓冲遇到`\n`,全缓冲区满),缓冲区会自动刷新。
- **手动刷新**:通过调用`fflush`函数,可以手动清空缓冲区,确保数据立即输出。### 缓冲区大小的设置:
- 缓冲区的大小通常是固定的,但某些实现可能允许通过特定的函数或方法来调整缓冲区的大小。
### 应用场景:
- **行缓冲**:适用于需要即时反馈的人机交互场景,如命令行工具的输出。
- **全缓冲**:适用于文件读写操作,可以提高I/O效率。
- **无缓冲**:适用于错误处理,确保错误信息能够立即输出,不丢失。### 调试和测试:
- 使用工具如`gdb`可以查看`FILE`结构体的状态,了解缓冲区的使用情况。
- 通过写入数据并观察其输出时机,可以测试缓冲区的工作机制。### 注意事项:
- 在使用标准I/O进行文件操作时,了解缓冲机制对于优化程序性能和确保数据正确性非常重要。
- 适当使用`fflush`可以控制数据的输出时机,尤其是在需要同步输出或处理大量数据时。通过以上总结,你可以更好地理解C语言标准I/O库中的缓冲机制,并在实际编程中合理利用这些机制来优化程序的I/O性能和行为。
6. **流的概念**:
- 流是数据的序列,可以是输入流或输出流。
- 在C语言中,`FILE`结构体定义了流,而`FILE*`(流对象或文件流指针)用于指向流。
7. **流的分类**:
- 文本流:以文本形式处理数据,通常使用ASCII或UTF-8编码。
- 二进制流:以二进制形式处理数据,不进行任何转换。
8. **标准I/O的函数**:
- 一些常用的标准I/O函数包括:
- `printf`和`scanf`:用于格式化输出和输入。
- `sprintf`:将格式化的数据写入字符串。
- `getchar`和`putchar`:读取和写入单个字符。
- `fgets`和`fputs`:读取和写入字符串。
- `fread`和`fwrite`:读取和写入数据块。
- `ftell`:获取当前文件位置指针的位置。
- `rewind`:将文件位置指针重置到文件开头。
- `fseek`:设置文件位置指针到指定位置。
9. **标准I/O的预定义流**:
- `stdin`:标准输入流,通常用于从键盘读取数据。
- `stdout`:标准输出流,通常用于向显示器输出数据。
- `stderr`:标准错误流,用于输出错误信息。
10. **`man`命令的使用**:
- `man`命令用于查看Linux下的手册页,提供有关命令、系统调用和库函数的信息。
- `man`后面可以跟数字和命令名来查看不同部分的手册,例如:
- `man 1 command`:查看用户命令的帮助。
- `man 2 syscall`:查看系统调用的帮助。
- `man 3 function`:查看标准库函数的帮助。
以上是C语言编程中进行输入输出操作的基础。
文件操作步骤:
1,打开文件 FILE
2,io操作,,读写操作
3,关闭文件
下面介绍常用的相关函数
1.fopen
FILE *fopen(const char *path, const char *mode);
功能:
打开一个文件并建立一个流
参数:
path:要打开文件的路径
mode:
r 只读
文件不存在报错
文件存在则只读打开
r+ 读写
文件不存在报错
文件存在则读写打开
w 只写
文件不存在则创建
文件存在则清0只写打开
w+ 写读
文件不存在则创建
文件存在则清0写读打开
a 追加可写
文件不存在则创建
文件存在则追加只写打开 定位到文件最后增加内容。
a+ 追加读写
文件不存在则创建
文件存在则追加读写打开
返回值:
成功返回建立的文件流指针
失败返回NULL
2. fputc
int fputc(int c, FILE *stream);
功能:
向流中写入一个字符
参数:
c:要写入的字符
stream:文件流指针
返回值:
成功返回写入的字符ASCII码值
失败返回EOF
3.fgetc
int fgetc(FILE *stream);
功能:
从流中读取一个字符
参数:
stream:文件流指针
返回值:
成功返回读到字符的ASCII码值
读到文件末尾返回EOF
失败返回EOF -1
c= fgetc(stdin);
fputc(c,stdout);
获取键盘上面的输入,显示到屏幕。
4.feof
feof() 函数判断
int feof(FILE *stream);
功能:判断当前参数stream的文件流指针是否到达文件结尾。
如果到达文件结尾则返回真,否则返回假
注意:该操作一定要在一次IO操作之后判断。
参数:stream 要判断结尾的文件流对象
返回值:成功到达结尾是 真
否则 是假
5.fgets
char *fgets(char *s, int size, FILE *stream);
功能:从stream流对象关联的文件中获取size大小字节的文本数据
并存储到s对应的本地内存(栈区数组,堆区内存)
参数: s 要存储数据的本地内存
size 要获取的数据长度,单位字节。
stream 要获取的目标文件流对象,
可以是stdin ,程序会阻塞等待
如果是普通文件fp 则指向文件第一行数据
返回值:成功 返回指向有效数据的首地址,一般等于s的地址
失败 或者 文件末尾 NULL;
6.fputs
int fputs(const char *s, FILE *stream);
功能:从s所在的本地内存中获取一行数据,并写入stream对应的文件
流对象。
参数: s 要写的信息,一般是固定的字符串或者有数据的数组。
stream 要写入的目标文件流对象
返回值:成功 nonnegative number on success
失败 -1;
char buf[50];
gets(buf);
7.补充:fgets和gets的区别
1.gets是危险的,因为没有规范读
到数据的上限
2.gets会去掉从终端读入的\n字符
3.fgets会读到n个数据,如果n个
数据中存在\n字符则立即停止当
前的读取操作
4.fgets不会去掉从流中读到的\n字
符
8.二进制文件读写: fread()/fwrite()
读:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:从指定的stream流对象中获取nmemeb个大小为size字节的数据块到ptr
所在的本地内存中。
参数:ptr 要存储数据的本地内存一般是数组或者结构体指针
size 单个数据块的元数据大小。最小单元的大小
nmemb 要获取的数据块的个数,拷贝的数据块个数。
stream 要获取数据的源文件流对象,如果是stdin表示从
键盘获取数据,如果是fp文件则表示从普通文件获取。
返回值:成功 小于等于nemeb的整数,表示获取的数据长度
失败 小于0,结尾 0;
写:
size_t fwrite(const void *ptr, size_t size,size_t nmemb, FILE *stream);
功能:从ptr所在本地内存中取出nmemb个大小为size的数据块写入到stream流对应
的文件流对象中。
参数:ptr 要写的数据块地址,一般是数组或者结构体指针
size 要写的数据块元数据大小,单位是字节
nmemb 要写的数据块的个数
stream 要写的目标文件流对象。如果是stdout则表示数据会
写到终端屏幕显示,如果是fp的普通文件则会写入到文件中。
返回值:成功 小于等于nmemb 的个数。
失败 <0
标准IO之文件定位:fseek() ftell() rewind()
1.fseek
int fseek(FILE *stream, long offset, int whence);
功能:将stream流文件中的文件指针从whence位置开始
偏移offset字节的长度。
参数:stream 要移动文件指针的目标文件流对象。
注意:不支持设备文件,一般用于普通文件。
offset 要在文件内偏移的距离,单位字节。
如果值为整数,则向文件末尾偏移
如果值为负数,则向文件开头偏移
whence 偏移的起始位置,由系统定义的三个宏开始。
SEEK_SET 文件的开头位置
SEEK_CUR 文件的当前位置
SEEK_END 文件的末尾位置
返回值:
成功: 返回 0
失败: -1;
如果从文件的指定位置向后偏移过程中已经超过了文件
的当前末尾位置,则会自动以'\0'来填充文件内容,从
而形成一种被称为"空洞文件" 的特殊文件。
2.rewind
rewind() 等效于:fseek(stream,0L,SEEK_SET);
long ftell(FILE *stream);rewind(fp);
功能:获取当前文件流指针的具体位置,一般以文件
开头到当前指针的字节数为返回值。
参数:stream 要返回指针距离的文件流对象
返回值:成功 获取到的距离长度,单位是字节
失败 -1;
以上的所有函数都可以在man手册中找到,关于参数及返回值会有更详细的描述。