IO
标准IO:通过缓冲(缓存)减少系统调用,提高效率
无系统代码直接调用硬件,有系统用系统
流(标准IO)
c标准定义
linux最多能自建1021个流,加上预定义3个流刚好为1024
标准IO预定义3个流
标准输入流stdin / 标准输出流stdout / 标准错误流stderr
文本流
windows:换行符对应‘/r’ ‘/n’
linux:换行符对应‘/n’
二进制流
windows:换行符对应‘/n’
linux:换行符对应‘/n’
缓冲
全缓冲(打开默认文件)
当缓冲区无数据/无空间才执行IO操作
行缓冲
输入输出遇到换行符执行IO操作
流与一个终端关联时是典型的行缓冲
代码中打印信息最好加上换行符
无缓冲
错误信息
打开流
FILE *fopen(const char *path, const char *mode);成功返回流指针,错误返回空
r(文本)/rb(二进制):只读,必须有这个文件
r+(文本)/r+b(二进制):读写,必须有这个文件
w(文本)/wb(二进制):只写,有则清空文件,无则创建
w+(文本)/w+b(二进制):读写,其余同w
a(文本)/ab(二进制):只写,无则创建,有则末尾添加内容
a+(文本)/a+b(二进制):读写,其余同a
fopen创建文件权限为0666(rw-rw-rw-),linux有umask((022)&创建文件的权限)控制权限
用户可以更改umask,但仅影响当前文件
处理错误信息
extern int errno;存放错误号
void perror(const char *s);先输出s,再输出错误号对应错误信息
char *strerror(int errno);根据错误号返回对应错误信息
关闭流
int fclose(FILE *stream);成功返回0,失败返回EOF并设置errno
流关闭会自动刷新缓冲中的数据并释放缓冲区
程序正常终止会自动关闭所有流
关闭流后不可再去访问
读写流(错误或返回为EOF(-1))
fgetc()读一个字符/fputc()写一个字符 效率低
fgets()读一行/fputs()写一行 适用文本文件(二进制文件会出问题)
fread()读若干对象/fwrite()写若干对象 文本文件和二进制文件都适用(推荐使用)
diff -ruN用于比较文本文件
gets()容易造成缓冲区溢出
fgets()读完会在最后添加‘/0’结尾,换行符也会保留,当内容放不下时会读取size-1个字符,最后一位存‘/0’
puts()在输出完后会追加‘/n’,fputs()不会
刷新流
当缓冲区满时系统会自动刷新
int fflush(FILE *fp);成功返回0,失败返回EOF(-1)
linux只能刷新缓冲区,将内容存入文件
定位流
long ftell(FILE *stream);成功返回读写位置,失败返回EOF(-1)
long fseek(FILE *stream, long offset, int whence);成功返回0,失败返回EOF(-1),whence是设置基准点,SEEK_SET开始位置/SEEK_CUR当前位置/SEEK_END结束位置
void rewind(FILE *stream);定位到开始位置
其他
int ferror(FILE *stream);返回1代表流出错
int feof(FILE *stream);返回1代表到文件末尾
格式化输出
int fprintf(FILE *stream, const char *fmt, 。。。);将内容输出到流中
int sprintf(char *s, const char *fmt, 。。。);将内容输出到缓冲区中
sleep函数在unisd.h中,使用该函数需要引用这个文件
使用时间需要精确到秒就需要引入time.h
使用字符串需要引用string.h
%02d代表该数据占两位
文件IO
遵循操作系统标准,无缓冲,通过文件描述符打开文件,使用更加广泛
标准IO基于文件IO
打开文件需要引用fcntl.h
int open(const char *path, int oflag, 。。。);打开文件,成功返回文件描述符,失败返回EOF(-1);仅打开只需两个参数,创建需要用到三个参数
关闭/读取/写入/定位文件需要引用unistd.h
int close(int fd);成功返回0,失败返回EOF(-1)
关闭后文件描述符不再代表文件
ssize_t read(int fd, void *buf, size_t count);成功返回实际读取字节数,失败返回EOF(-1),读到末尾返回0;buf是缓冲区大小,count不能超过buf大小
ssize_t write(int fd, void *buf, size_t count);成功返回实际写入字节数大小,失败返回EOF(-1);buf是缓冲区大小,count不能超过buf大小
off_t Iseek(int fd, off_t offset, intt whence);成功返回当前文件读写位置,失败返回EOF(-1);后两个参数和标准IO的定位函数中一致
访问/关闭目录需要引用dirent.h
DIR *opendir(const char *name);
DIR为描述一个打开的目录文件的结构体类型
成功返回目录流指针,失败返回EOF(-1)
struct dirent *readdir(DIR *dirp);读取目录中的内容
struct dirent用于描述目录流中一个目录项的结构体类型
成功返回目录流dirp中下一个目录项,失败返回NULL
int closedir(DIR *dirp);成功返回0,失败返回EOF(-1)
修改文件访问权限/获取文件属性需要引用sys/stat.h
int chmod(const char *path, mode_t mode);通过路径修改权限
int fchmod(int fd, mode_t mode);通过文件描述符修改权限
成功返回0,失败返回EOF(-1)
root和文件所有者可修改文件访问权限
int stat(const char *path, struct stat *buf);获取符号链接的目标文件的属性
int Istat(const char *path, struct stat *buf);获取符号链接的文件的属性
int fstat(int fd, struct stat *buf);
成功返回0,失败返回EOF(-1)
自编写的库在编译时需要在命令后添加 -L位置 -l函数名
-fPIC文件位置不固定,.a是静态库,.so.X是共享库(动态库)
共享库需要编辑环境中的路径或者在/etc/ld.so.conf.d/下添加一个conf结尾的文件,执行ldconfig刷新