2.文件IO
2.文件IO
- **1. 文件I/O概述**
- **2. 文件I/O函数接口**
- **3. 文件定位**
- **4. 文件描述符与文件流指针的转换**
- **5. 文件I/O与标准I/O的比较**
- **6. 练习与作业**
- **7. 文件I/O与标准I/O的对应关系**
- **8. 其他注意事项**
- **9. 总结**
1. 文件I/O概述
- 文件I/O:操作系统为了方便用户使用系统功能而提供的一组系统函数,称为系统调用。文件I/O是其中的一部分。
- 特性:
- 没有缓存区。
- 操作对象是文件描述符(
int
类型),而不是流(FILE*
)。 - 文件描述符是一个很小的非负整数(0-1023),内核每打开一个文件就会分配一个文件描述符。
- 默认文件描述符:
0
:STDIN_FILENO
(标准输入,对应stdin
)。1
:STDOUT_FILENO
(标准输出,对应stdout
)。2
:STDERR_FILENO
(标准错误,对应stderr
)。
2. 文件I/O函数接口
- open:
- 函数原型:
int open(const char *pathname, int flags, int mode);
- 功能:打开文件并返回文件描述符。
- 参数:
pathname
:文件名。flags
:打开文件的模式(如O_RDONLY
、O_WRONLY
、O_RDWR
等)。mode
:文件权限(如0666
)。
- 返回值:成功返回文件描述符,失败返回
-1
。
- 函数原型:
- write:
- 函数原型:
ssize_t write(int fd, const void *buf, size_t count);
- 功能:向文件中写入数据。
- 参数:
fd
:文件描述符。buf
:要写入的数据缓冲区。count
:要写入的字节数。
- 返回值:成功返回实际写入的字节数,失败返回
-1
。
- 函数原型:
- read:
- 函数原型:
ssize_t read(int fd, void *buf, size_t count);
- 功能:从文件中读取数据。
- 参数:
fd
:文件描述符。buf
:存放读取数据的缓冲区。count
:要读取的字节数。
- 返回值:成功返回实际读取的字节数,失败返回
-1
,读到文件末尾返回0
。
- 函数原型:
- close:
- 函数原型:
int close(int fd);
- 功能:关闭文件描述符。
- 返回值:成功返回
0
,失败返回-1
。
- 函数原型:
3. 文件定位
- lseek:
- 函数原型:
off_t lseek(int fd, off_t offset, int whence);
- 功能:移动文件指针。
- 参数:
fd
:文件描述符。offset
:偏移量(正数向后偏移,负数向前偏移)。whence
:起始位置(SEEK_SET
、SEEK_CUR
、SEEK_END
)。
- 返回值:成功返回偏移量,失败返回
-1
。
- 函数原型:
- lseek与fseek的区别:
lseek
不支持O_APPEND
模式,无法生成空洞文件。lseek
在设备文件上偏移无效。
4. 文件描述符与文件流指针的转换
- fileno:
- 函数原型:
int fileno(FILE *stream);
- 功能:将文件流指针(
FILE*
)转换为文件描述符(int
)。 - 返回值:成功返回文件描述符,失败返回
-1
。
- 函数原型:
- fdopen:
- 函数原型:
FILE *fdopen(int fd, const char *mode);
- 功能:将文件描述符(
int
)转换为文件流指针(FILE*
)。 - 参数:
fd
:文件描述符。mode
:打开模式(如"r"
、"w"
等)。
- 返回值:成功返回文件流指针,失败返回
NULL
。
- 函数原型:
5. 文件I/O与标准I/O的比较
- 文件I/O:
- 无缓存,直接操作文件描述符。
- 适用于底层设备开发,效率和安全性较低。
- 标准I/O:
- 有缓存,操作对象是文件流指针(
FILE*
)。 - 适用于上层开发,效率高且移植性好。
- 有缓存,操作对象是文件流指针(
6. 练习与作业
- 练习1:使用文件I/O测试无缓存特性,验证终端和文件的直接读写。
- 练习2:封装一个简单的
printf
函数,支持缓存和直接输出。 - 作业1:使用文件I/O完成两个文件的比较功能,测试文件是否相等。
- 作业2:使用文件I/O向终端输出100以内的所有偶数。
7. 文件I/O与标准I/O的对应关系
标准I/O | 文件I/O |
---|---|
fopen | open |
fputc / fgetc | write / read |
fputs / fgets | write / read |
fwrite / fread | write / read |
fclose | close |
fseek | lseek |
ftell | lseek |
rewind | lseek(fd, 0, SEEK_SET) |
8. 其他注意事项
- 文件描述符的最大值:1024(范围0-1023),可通过
ulimit -a
查看。 - 阻塞与非阻塞:
- 阻塞:程序因某种条件未触发而暂停执行。
- 非阻塞:程序继续执行,不等待条件触发。
9. 总结
文件I/O是操作系统提供的底层接口,适用于设备相关的开发。与标准I/O相比,文件I/O没有缓存,操作对象是文件描述符。通过open
、read
、write
、close
等函数可以实现文件的读写操作。文件I/O与标准I/O各有优缺点,开发时应根据需求选择合适的I/O方式。