(一)标准IO
1.一些基本概念
(1)三种缓冲模式
全缓冲:缓冲区满才会刷新缓冲区,或者用fflush强制刷新进行实际的I/O操作。
对于存放在磁盘上的普通文件用标准I/O打开时默认是全缓冲的。
行缓冲:输入/输出中遇到换行符'\n'时执行I/O操作。
stdin/stdout是行缓冲,行缓冲区满了才刷新,或者遇到'\n'
无缓冲:不使用缓冲区进行I/O操作。
stderr是无缓冲,发生错误时,错误信息直接显示在终端上
perror函数报错也是无缓冲,比如perror("open():");会打印open()出错的原因
//perror函数括号里的字符串会默认加上“:”输出到终端,后面跟原因
//void perror(const char *s)
(2)标准io与系统io
标准io使用了缓冲区,使得吞吐量比系统io更快,系统io需要频繁变态
文件流就是FILE类型的结构体
2.标准IO的函数
1.fopen()
FILE *fopen(const char *path,const char *mode)
// path:要打开的文件的路径及文件名
// mode:文件打开方式,有r,r+,w,w+,a,a+
返回指向FILE结构体的指针,如果返回NULL,表示打开失败了
2.fclose()
int fclose(FILE *stream)
stream是指向你要关闭的文件对应的FILE结构体的流指针
关闭成功返回0,失败返回EOF
3.格式化输入输出
int printf(const char *format,...);
int fprintf(FILE *fp,const char *format,...);
int sprintf(char *buf,const char *format,...);
int scanf(const char *format,...);
int fscanf(FILE *fp,const char *format,...);
int sscanf(char *buf,const char *format,...);
函数返回值: 成功:读到的数据个数
失败:EOF
4.fread()
size_t fread(void *ptr,size_t size,size_t nmemb,FILE *stream);
// ptr:存放读入数据的缓冲区
// size:读取的每个数据项的大小(单位字节)
// nmemb:读取的数据个数
// stream:要读取的流
函数返回值:成功:实际读到的nmemb数目
失败:0
5.fwrite()
size_t fwrite(void *ptr,size_t size,size_t nmemb,FILE *stream);
// ptr:存放写入数据的缓冲区
// size:写入的每个数据项的大小(单位字节)
// nmemb:写入的数据个数
// stream:要写入的流
函数返回值:成功:实际写入的nmemb数目
失败:0
6.fseek()
int fseek(FILE *stream,long offset,int whence);
SEEK_SET:代表文件起始位置,数字表示为0
SEEK_CUR:代表文件当前的读写位置,数字表示为1
SEEK_END:代表文件结束位置,数字表示为2
函数返回值:成功返回0,改变读写位置 失败返回EOF,不改变读写位置
7.ftell()
int ftell(FILE *stream);
函数返回值:成功返回当前的读写位置 失败返回EOF
8.fflush()
int fflush(FILE *stream);
函数返回值:成功返回0 失败返回EOF
9.feof()
int feof(FILE *stream);
函数返回值:文件结束返回非0的值,文件未结束返回0
if(feof(stream))//判断该流是否已结尾
while(!feof(stream))//循环操作该流直至文件结尾
10.rewind()
void rewind(FILE *stream);
rewind()函数会将当前读写位置返回至文件开头
等价于(void)fseek(stream, 0L, SEEK_SET)
11.putc,puts,fputc,fputs,putchar
puts(const char *s) = fputs(const char *s , stdout )
putc(int c, FILE* stream)和fputc(int c, FILE* stream)没有区别
putchar(int c) = putc(int c, stdout)
注:向文件中写入数据一般用fprintf不用fputs
12.getc,gets,fgetc,fgets,getchar
getc和fgetc一个是宏,一个是函数,getc是fgetc通过宏实现,使用上没啥区别
getchar(int c)=fgetc(int c, stdin)
char *gets(char *s) 永远不用gets,会导致缓冲区溢出
char *fgets(char *s,int size,FILE *stream)
fgets:
1.返回值: 成功是s,s用来保存读取的内容,
失败或读到EOF是 NULL(一般都是读完文件,很少出错);
2.从stream中获取最多size-1个大小字符然后加'\0',或者没获取到size-1个字符中间遇到了'\n';
(二)文件IO(系统调用IO)
1.文件io和标准io之间的转化
int fileno(FILE * stream); //将FILE指针传进来,返回该文件的fd
FILE *fdopen(int fd, const char* mode); //将fd传进来,封装成该文件的FILE*指针
2.补充函数
int truncate(const char* path, off_t length);
int truncate(int fd, off_t length);
3.程序中的重定向dup,dup2
int dup(int oldfd);使用最小的fd,把oldfd的内容拷贝到那个fd中,这样两个fd指向同一个结构体
int dup2(int oldfd, int newfd);
close(1);dup(fd);close(fd);相当于dup2(fd,1); if(fd!=1) close(fd);
4.同步:sync,fsync,fdatasync
void sync(void);把缓冲区和cache中内容同步到disk
int fsync(int fd);同步一个文件的buffer和cache
int fdatasync(int fd);只刷数据,不刷亚数据(比如文件的修改时间)
5.fcntl()和ioctl()
文件描述符相关几乎来源于fcntl,设备相关的内容ioctl
6.文件IO编程
(1)打开文件
open()系统调用需要包含头文件 #include<sys/stat.h>和#include<fcntl.h>
函数原型:int open(const char *pathname,int flags,int perms);
//pathname:打开文件名(可以包含具体路径名)
例如/tmp/aaa.c 或者把argv[0]传进去也行,执行时手动输入argv[0]的内容
//flags:打开文件的方式
例如以可读形式打开有则截断无则创建:O_RDONLY|O_CREAT|O_TRUNC
//perms:新建文件的权限
例如perms=0666:第一个0表示这是八进制数,后面表示 文件所有者/文件组/其他用户 的权限
r4 w2 x1 6=4+2表示可读可写
函数返回值:成功是文件描述符fd,失败返回-1
(2)关闭文件
close()系统调用需要头文件:#include<unistd.h>
函数原型:int close(int fd);
//fd:文件描述符
函数返回值:成功返回0,失败返回-1
(3)读写文件
read()系统调用需要头文件:#include<unistd.h>
函数原型:int read(int fd,void *buf,size_t count);
//fd:文件描述符
//buf:读取出的数据存放到缓冲区的地址
//count:读取的字节数
函数返回值:成功是读到的字节数 或 0(表示文件已结尾),失败返回-1
write()系统调用需要头文件:#include<unistd.h>
函数原型:ssize_t write(int fd,void *buf,size_t count);
//fd:文件描述符
//buf:写入的数据存放到缓冲区的地址
//count:指定写入的字节数
函数返回值:成功是写入的字节数,失败返回-1
(4)lseek()函数
lseek()系统调用需要包含头文件:#include<unistd.h> 和 #include<sys/types.h>
函数原型:off_t lseek(int fd,off_t offset,int whence);
//fd:文件描述符
//offset:相对偏移量,正数表示向前移动,负数表示向后移动,0表示不移动
//whence:文件头1,文件当前位置2,文件尾3
SEEK_SET SEEK_CUR SEEK_END
函数返回值:成功是当前读写位置,失败是-1
(三)文件系统
一.目录和文件
1.获取文件属性
在当前目录创建一个文件-a:所用命令 touch -- -a或者touch ./-a
ls -a 显示所有文件
ls -i 显示inode
ls -n 显示userID和groupID
ls -l 显示user名和group名
int stat(const char * path, struct stat * buf); //把path路径下的文件对应的stat结构体地址传到buf中
int fstat(int fd, struct stat * buf);//把文件描述符fd对应的文件对应的stat结构体地址传到buf中
int stat(const char * path, struct stat * buf);
// struct stat是一个结构体,存放了各种关于文件的属性
//返回值小于0那么就失败了,用perror("stat()");报错,然后exit(1);
stat命令:stat 文件名: 可以显示文件的stat,实质是用stat函数封装的
空洞文件:文件里全都是空字符
linux文件类型:- 普通文件 d 目录文件 c 字符设备 b块设备 p 命名管道 l 符号链接 s 网络套接字
2.文件访问权限
st_mode是一个16bit的位图,
用于表示文件类型,文件访问权限,以及特殊权限位(针对其他用户的权限eg:是否可读可写)
3.umask
umask命令实际上是一个系统调用,目的是为了防止产生权限太松的文件
如果你创建文件时没有设置权限,就会默认设置 0666&^umask
umask + 三位八进制数:可以设置umask的值(第一个0表示这是八进制数)
umask 0002
umask + 回车:可以查看当前umask的值
0666&^umask 就是 110 110 110 & 111 111 101 = 110 110 100 (0664)
4.文件权限的更改与管理
(1)chmod命令
①chmod + 权限值 + 要修改权限的文件名 + 回车
eg: chmod 666 big.c
ls -l big.c
会发现前面变成 -rw-rw-rw-
②chmod a/u/g/o+x big.c
(2)chmod函数和fchmod函数
int chmod(const char* path, mode_t mode); 针对某个文件更改权限
int fchmod(int fd, mode_t mode); 针对某个打开的文件更改权限
5.粘住位
t位,一般给常用的目录设置t位,访问更快
6.文件系统:FAT,UFS
7.硬链接,符号链接
8.utime
可以更改文件的最后一次读的时间atime和最后一次写的时间mtime
9.目录的创建和销毁
mkdir
rmdir 只能删除空目录,不然要递归删除
10.更改当前工作路径 cd命令
实际上是用了系统调用
chdir
fchdir
getcwd 获取当前工作目录,命令是cwd