标准IO
概念
在C库中定义的一组专门用于输入输出的函数
特点:
通过缓冲机制减少系统调用
围绕流进行操作,流使用FILE *来描述
标准IO默认打开了三个流:标准输入(stdin)、标准输出(stdout)、标准错误(stderr)
缓存区
全缓存:与文件相关
刷新缓存的条件:
程序正常退出
缓存区满刷新
强制刷新fflush行缓存:与终端相关
刷新缓存的条件:
换行\n程序正常退出
缓存区满刷新
强制刷新:fflush
不缓存:标准错误
没有缓存,直接刷新
函数接口
#include <stdio.h>
FILE *fopen(const char *path,const char *mode);
//功能:打开文件
/*
参数:
path:打开的文件
mode:打开的方式
r:只读,当文件不存在时报错,文件流定位到文件开头
r+:可读可写,当文件不存在时报错,文件流定位到文件开头
w:只写,文件不存在创建,文件存在则清空
w+:可读可写,文件不存在创建,文件存在则清空
a:追加(在末尾写),文件不存在则创建,存在追加,文件流定位到文件末尾
a+:读和追加,文件不存在则创建,存在则追加,读文件流定位到文件开头,写文件流定位到文件末尾
注意:当a的方式打开文件时,写只能在末尾进行追加,写文件流不能被修改位置,读文件流可以修改位置
返回值:
成功:文件流
失败:NULL,并设置错误码
*/
int fclose(FILE* stream);
//功能:关闭文件
/*
参数:
stream:文件流
*/
//读写文件
//单个字符的读写
int fgetc(FILE *stream);
//功能:从文件中读取一个字符
/*
参数:
stream:文件流
返回值:
成功:读到的字符
失败或者读到文件末尾:EOF(-1)
*/
int fputc(int c,FILE *stream);
//功能:向文件中写入一个字符
/*
参数:
c:要写的字符
stream:文件流
返回值:
成功:写的字符的ASCII
失败:EOF
*/
int feof(FILE *stream);
//功能:判断文件有没有到结尾
/*
参数:
stream:文件流
返回值:
达到文件末尾,返回非0值
*/
int ferror(FILE *stream);
//功能:cancel文件有无出错
/*
参数:
stream:文件流
返回值:
文件出错,返回非0值
*/
//每次一串字符的读写
char *fgets(char *s,int size,FILE *stream);
//功能:从文件中每次读取一行字符串
/*
参数:
s:存放字符串的地址
size:一次读取的字符个数
stream:文件流
返回值:
成功:s的地址
失败或读到文尾:NULL
特性:
每次实际读取的字符个数为size-1个,会在末尾自动添加\0
每次读取一行,遇到\n后不再继续读下一行
*/
int fpus(const char *s,FILE *stream);
//功能:向文件中写字符串
/*
参数:
s:要写的文件内容
stream:文件流
返回值:
成功:非负整数
失败:EOF
*/
//二进制读写
size_t fread(void *ptr,size_t size,size_t nmemb,FILE *stream);
//功能:从文件流读取多个元素
/*
参数:
ptr:用来存放读取元素
size:元素大小
nmemb:读取元素的个数
stream:要读取的文件
返回值:
成功:要读取的元素个数
读到文尾:0
失败:-1
*/
size_t fwrite(const void *ptr,size_t size,size_t nmemb,FILE *stream);
//功能:按对象写
/*
参数:
prt:用来存放写入元素
size:元素大小
nmemb:写入元素的个数
stream:要写入的文件流
返回值:
成功:写的元素个数
失败:-1
*/
//打开文件的另一种方式
FILE *freopen(const char * pathname,const char *mode,FILE *fp);
//功能:将指定的文件流重新定向到打开的文件中
/*
参数:
pathname:文件路径
mode:打开文件的方式:详述见fopen
fp:文件流指针
返回值:
成功:返回文件流指针
失败:NULL
*/
//示例:将文件流重新定向回stdin
FILE *fp=("/dev/pts/3",const char *mode,old_fp);
//文件定位操作
void rewind(FILE *stream);
//功能:将文件位置指针定位到起始位置
/*
参数:
stream:要操作的文件流
*/
int fseek(FILE *stream,long offset,int whence);
//功能:文件的定位操作
/*
参数:
stream:文件流
offset:偏移量:正数标识向文件尾部偏移,负数标识向文件开头偏移
whence:相对位置
SEEK_SET:相对于文件开头
SEEK_CUR:相对于文件当前位置
SEEK_END:相对于文件结尾
返回值:
成功:0
失败:-1
注意:当打开文件的方式为a或者a+时,fseek不起作用
*/
long ftell(FILE *stream);
//功能:获取当前文件流位置
/*
参数:
stream:要检测的文件流
返回值:
成功:返回当前文件流位置
失败:-1
*/
文件IO
概念
概念:posix中定义的一组用于输入输出的函数
特点:
没有缓冲机制,每次调用都会引起系统调用围绕文件描述符进行操作,非负整数(>=0),依次分配
文件IO默认打开了三个文件描述符,分别是0(标准输入),1(标准输出),2(标准错误)
可以操作除目录文件外的任意文件类型:bc-lsp
函数接口
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname,int flags);
//功能:打开文件
/*
参数:
pathname:文件路径名
flags:打开文件的方式
O_RDONLY:只读
O_WRONLY:只写
O_RDWR:可读可写
O_CREAT:创建
O_TRUNC:清空
O_APPEND:追加
返回值:
成功:文件描述符
失败:-1
*/
//注意:当第二个参数中有O_CREAT选项时,需要给open函数传递第三个参数,指定创建文件的权限
int open(const char *pathname,int flags,mode_t mode);
//创建出来的文件权限为指定权限值&(~umask) //umask为文件权限掩码
//案例:(权限值这样写,是一种不标准的写法)
int fp=open("./path",O_CREATE|O_WRONLY,0666);
//建议使用宏定义函数
int fp=open("./path",O_CREATE|O_APPEND,S_IRWXU);
标准IO及文件IO读写关系对应表
标准IO | 文件IO |
---|---|
r | O_RDONLY |
r+ | O_RDWR |
w | O_WRONLY|O_CREAT|O_TRUNC,0666 |
w+ | O_RDWR|O_CREAT|O_TRUNC,0666 |
a | O_WRONLY|O_CREAT|O_APPEND,0666 |
a+ | O_RDWR|O_CREAT|O_APPEND,0666 |
#include <unistd.h>
size_t read(int fd,void *buf,size_t count);
//功能:从一个已经打开的可读文件中读取数据
/*
参数:
fd:文件描述符
buf:存放位置
count:期望读取文件个数
返回值:
成功:实际读取到文件的个数
读到文件末尾:0
失败:-1并设置errno
*/
off_t lseek(int fd,off_t offset.int whence);
//功能:设定文件的偏移位置
/*
参数:
fd:文件描述符
offset:偏移量:同fseek,这里就不再赘述了
whence:相对位置:同fseek,这里就不再赘述了
返回值:
成功:文件指针当前位置
失败:-1
*/
标准IO与文件IO区别
标准IO:
概念:C库中定义的一组用于输入输出的函数
特点:
有缓冲机制
围绕流进行操作,FILE*
默认打开的三个流:stdout/stdin/stderr
只能操作普通文件
程序可移植性强
函数:
打开文件:fopen、freopen
关闭文件:close
读文件:fgetc、fgets、fread
写文件:fputc、fputs、fwrite
定位文件:fseek、frewind、ftell
文件IO:
概念:posix中定义的一组输入输出的函数
特点:
无缓冲机制
围绕文件描述符进行操作,非负整数 默认打开了三个文件描述符:0/1/2
可以操作除目录类型外的任意类型文件
函数:
打开文件:open
关闭文件:close
读文件:read
写文件:write
定位操作:lseek
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int stat(const char *path,struct stat *buf);
//功能:获取文件属性
/*
参数:
path:文件路径名
buf:保存文件属性信息的结构体
返回值:
成功:0
失败:-1
*/
//关于结构体
struct stat
{
ino_t st_ino; /* inode number inode号*/
mode_t st_mode; /* protection 文件类型权限*/
nlink_t st_nlink; /* number of hard links 硬链接数*/
uid_t st_uid; /* user ID of owner 用户ID*/
gid_t st_gid; /* group ID of owner 组ID*/
off_t st_size; /* total size, in bytes 文件大小*/
time_t st_atime /* 最后访问时间*/
time_t st_atime /* 最后修改时间*/
time_t st_atime /* 最后状态改变时间*/
};
//获取文件类型的方法一
if((st.stmode&S_IFMT)==S_IFREG){
putchar('-');
}
//获取文件类型的方法二
if(S_ISREG(st.st_mode)){
putchar('-');
}
文件类型获取宏函数及宏定义对比表
宏定义使用方法:
if(stat.mode&S_IFMT==宏定义位掩码)
中文含义 | 符号标识 | 宏定义位掩码 | 宏函数 |
---|---|---|---|
文件类型字段位掩码 | S_IFMT | S_ISSOCK(stat.mode) | |
套接字 | s | S_IFSOCK | S_ISLINK(stat.mode) |
链接文件 | l | S_IFLINK | S_ISREG(stat.mode) |
普通文件 | - | S_IFREG | S_ISBLK(stat.mode) |
块设备文件 | b | S_IFBLK | S_ISBLK(stat.mode) |
目录文件 | d | S_IFDIR | S_ISDIR(stat.mode) |
字符设备文件 | c | S_IFCHR | S_ISCHR(stat.mode) |
管道文件 | p | S_IFIFO | S_ISFIFO(stat.mode) |
//获取文件权限方法
if(st.st_mode&S_IRUSR){
putchar('r');
}else{
putchar('-');
}
权限掩码及权限值的具体含义
使用方法:
if(stat.st_mode&权限掩码)
权限掩码 | 用户 | 组 | 其他用户 | 读 | 写 | 执行 |
---|---|---|---|---|---|---|
S_IRWXU | √ | √ | √ | √ | ||
S_IRUSR | √ | √ | ||||
S_IWUSR | √ | √ | ||||
S_IXUSR | √ | √ | ||||
S_IRWXG | √ | √ | √ | √ | ||
S_IRGPR | √ | √ | ||||
S_IWGPR | √ | √ | ||||
S_IXGPR | √ | √ | ||||
S_IRWXO | √ | √ | √ | √ | ||
S_IROTH | √ | √ | ||||
S_IWOTH | √ | √ | ||||
S_IXOTH | √ | √ |
#include <sys/types.h>
#include <pwd.h>
struct passwd *getpwuid(uid_t uid);
//功能:获取用户信息
/*
参数:
uid:用户id
返回值:
用户信息结构体
*/
struct passwd
{
char *pw_name; /* username */
char *pw_passwd; /* user password */
uid_t pw_uid; /* user ID */
gid_t pw_gid; /* group ID */
char *pw_gecos; /* user information */
char *pw_dir; /* home directory */
char *pw_shell; /* shell program */
};
#include <sys/types.h>
#include <grp.h>
struct group *getgrgid(gid_t gid);
//功能:获取用户所在组信息
/*
参数:
gid:组ID
返回值:
组信息结构体
*/
struct group
{
char *gr_name; /* group name */
char *gr_passwd; /* group password */
gid_t gr_gid; /* group ID */
char **gr_mem; /* NULL-terminated array of pointers
to names of group members */
};
目录操作
概念
围绕目录流进行操作 DIR *
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
//功能:获得目录流
/*
参数:
*name:要打开的目录
返回值:
成功:目录流
失败:NULL
*/
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
//功能:要读取的目录流
/*
参数:
dirp:要读取的目录流
返回值:
成功:读到的信息
失败:NULL
*/
//返回值为结构体,该结构体成员为描述该目录下得文件信息
struct dirent
{
ino_t d_ino; /* inode number 索引节点号*/
off_t d_off; /* not an offset; see NOTES 文件在目录中的偏移*/
unsigned short d_reclen; /* length of this record 文件名长度*/
unsigned char d_type; /* type of file; not supported
by all filesystem types 文件类型 */
char d_name[256]; /* filename 文件名*/
};
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
//功能:关闭目录
/*
参数:
dirp:目录流
返回值:
成功:0
失败:-1
*/
库的简单介绍
概念
当使用别人的函数时,除了包含头文件以外还要有库
头文件的内容包含:函数声明、结构体等类型定义,头文件,宏定义等
库:就是把一些常用的目标文件打包在一起,提供相应的函数接口,便于程序员使用,本质上来说,库是一种可执行代码的二进制形式
但是不同操作系统的库文件互不兼容
库的分类
静态库和动态库,二者的本质区别是载入时间不同
静态库:
静态库在程序编译时会被连接到目标代码中
优点:
程序运行时不再需要该静态库,运行时无需加载该库,运行速度更快
缺点:
静态库中的代码复制到了程序中,因此体积较大
静态库升级后,程序需要重新编译链接
动态库: 动态库实在程序运行时被载入代码
优点:
程序在执行时被加载到动态库,代码体积小 程序升级更加简单
不同应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例
缺点:
运行时还需要该动态库的存在,可移植性较差