之前学了标准IO,这篇整理文件IO的部分。文件IO是Linux内核提供的接口,属于系统调用,操作对象是文件描述符而不是FILE指针。核心就四个:open打开、read读、write写、close关闭。
open
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
打开一个文件,返回文件描述符,失败返回-1。
flags是打开方式,常用的:
– O_RDONLY:只读
– O_WRONLY:只写
– O_RDWR:读写
– O_CREAT:创建
– O_TRUNC:清空
– O_APPEND:追加
可以组合使用,比如标准IO的"w"对应 O_WRONLY | O_TRUNC | O_CREAT ,mode给0664。"a"对应 O_WRONLY | O_CREAT | O_APPEND 。
mode参数是文件权限,实际权限是 mode & ~umask ,普通文件一般给0664。
文件描述符:打开文件时系统分配的一个小的非负整数,用来标记这个文件。默认范围0-1023,共1024个,分配原则是最小未被使用。系统默认已经打开三个:
– 0 —— STDIN_FILENO,标准输入
– 1 —— STDOUT_FILENO,标准输出
– 2 —— STDERR_FILENO,标准出错
close
#include <unistd.h>
int close(int fd);
关闭文件,成功返回0,失败返回-1。打开的文件用完一定要关,不然会造成文件描述符泄露。
write
ssize_t write(int fd, const void *buf, size_t count);
向文件写入count字节的数据,成功返回实际写入的字节数,失败返回-1。
read
ssize_t read(int fd, void *buf, size_t count);
从文件读取数据,成功返回实际读到的字节数,到达文件末尾返回0,失败返回-1。
用read和write实现文件拷贝:
int file_copy(const char *srcfile, const char *dstfile)
{
int fdsrc = open(srcfile, O_RDONLY);
int fddst = open(dstfile, O_WRONLY | O_CREAT | O_TRUNC, 0664);
if (-1 == fdsrc || -1 == fddst)
{
printf("open error\\n");
return -1;
}
char buff[1024] = {0};
ssize_t size = 0;
while ((size = read(fdsrc, buff, sizeof(buff))) > 0)
{
write(fddst, buff, size);
}
close(fdsrc);
close(fddst);
return 0;
}
lseek
off_t lseek(int fd, off_t offset, int whence);
重新定位文件的读写位置。whence有三个取值:
– SEEK_SET:从文件开头偏移
– SEEK_CUR:从当前位置偏移
– SEEK_END:从文件末尾偏移
成功返回当前位置到文件开头的偏移量,失败返回-1。可以用来求文件大小,也可以创建空洞文件抢占磁盘空间。
文件IO和标准IO的区别
标准IO 文件IO
操作对象 FILE *(文件流指针) fd(文件描述符)
性质 标准C库函数,可移植性强 Linux系统调用,可移植性弱
缓冲区 有缓冲区,减少用户层和内核层切换,效率高 无缓冲区,实时性好
适用场景 主要操作普通文件 普通文件、硬件设备类文件
标准IO的缓冲区分三种:
– 行缓冲:默认1K,用在终端交互。遇到'\\n'刷新、程序结束刷新、fflush强制刷新、缓冲区满刷新。
– 全缓冲:默认4K,文件交互。程序结束刷新、文件关闭刷新、缓冲区满刷新、fflush强制刷新。
– 无缓冲:0K,比如stderr,出错信息直接输出。
其他
几个格式化输出和字符串处理函数:
int printf(const char *format, …);
int fprintf(FILE *stream, const char *format, …);
fprintf把格式化后的字符串写入指定的文件流。
int dprintf(int fd, const char *format, …);
dprintf写入到文件描述符代表的文件中。
int sprintf(char *str, const char *format, …);
sprintf把格式化后的字符串写入字符数组,常用于字符串拼接、把整型或浮点型转成字符串。
char *strtok(char *str, const char *delim);
字符串截取函数。str是原始字符串,delim是分隔符。成功返回截取到的子字符串首地址,到末尾返回NULL。第一次调用传str,后续传NULL继续截取。



