文件和目录
stat()/fstat()/lstat() 成功返回0,出错返回-1.
获取与文件目录有关的信息结构,fstat参数为已打开的文件描述符,而lstat
可以处理符号链接,当文件是一个符号链接时,返回的是符号链接的信息而不是引用文件的信息(否则在处理目录时可能引起死循环)。
信息结构struct stat 的大部分信息都取自i节点,文件名和i节点存放于目录项。具体信息一般有文件类型、i节点号、文件所有者、文件大小、文件时间、文件链接数等。
目录相关的函数:
mkdir() - 新建一个空目录(mkdir命令)
rmdir()- 删除一个空间目录(rmdir命令)
chdir() - 切换当前的目录(cd命令)
getcwd - 获得当前目录的绝对路径形式(双返回)但不打印
实现读取目录中的内容:
opendir() - 打开一个目录
readdir()- 读目录的内容(子项,子文件或子目录)
closedir()- 关闭已经打开的目录(不关闭也行)
读某个目录内容(子项)的步骤:
1. opendir()返回目录指针
2. 循环调用readdir(),逐一读取每个子项。(忽略“.”和“..”)
3. closedir()关闭目录,这步也可以省略。
文件i/o
Linux系统中一切皆文件,目录、内存、各种硬件设备都可以当作文件操作。
/dev/tty - 键盘,也代表 显示器
/dev/null - 空设备,就是用于清空东西的 虚拟设备
cat /dev/null > a.txt - 清空a.txt
ls -l > /dev/null - 执行命令,但不做任何的显示
系统调用方式访问文件
每个进程在进程表中维持一个记录项,其中包含打开的文件描述符表,文件描述符是一个非负整数,每个描述符对应一张文件表。
0 1 2 已经被系统预先使用,代表标准输入、标准输出和标准错误。文件描述符从3开始,最大到OPEN_MAX。文件描述符可以循环利用,close()以后就可以再次使用。
int creat ( constchar *filename ,mode_t mode )
常见创建模式:
S_IRUSR 可读;S_IWUSR可写;S_IXUSR 可执行 ; S_IRWXU可读写执行
除了使用上述宏以外还可以直接使用数字来表示文件的访问权限
例如:creat (filename ,0755);
int open (constchar *path ,int flags, mode_t mode )
当打开文件不存在时使用O_CREAT标志,并使用第三个参数。
常见打开标志:
O_RDONLY O_WRONLY O_RDWR : 打开的权限。
O_CREAT : 创建标识,文件存在就打开,不存在就新建
O_TRUNC : 打开文件时自动清空文件(open是清空)
O_EXCL : 文件不存在新建,存在就返回-1代表出错
上面两个一般都是和O_CREAT结合使用
O_APPEND : 采用追加的方式打开文件,一般用于写。
close()函数用于关闭文件描述符,不一定关闭文件表。close()其实就是在描述符总表中移除对应关系,文件表的计数会减1,当文件表的计数到0时,文件表就可以被回收。
读写函数:
int read(int fd,void* buf,size_t count)
int write(int fd,void* buf,size_t length)
参数count是buf的真实大小,不一定读满
参数length不是buf的大小,而是 写入数据的大小
read() 返回 正数就是真实读到的字节数,0代表读完了,-1代表出错。
write()返回正数 就是真实写入的字节数,0代表什么都没写,-1代表出错。
系统有一个权限屏蔽字,默认权限屏蔽是屏蔽其他用户的写权限,权限屏蔽字可以修改。
mode_t umask(mode_t cmask)
传入新的屏蔽字,返回旧的屏蔽字。
off_t lseek (intfd ,off_t offset ,int whence ) 文件定位,即文件偏移量。
返回: 移动以后的位置和文件头的距离,失败返回 -1 。
基准点whence使用下述值:
SEEK_SET相对文件开头;SEEK_CUR文件读写指针的当前位置;SEEK_END末尾
offset可取负值例如:lseek( fd,-5,SEEK_CUR)
使用VIM时都会在文件末尾加一个\n,因此文件大小会多一个字节。
int access (constchar *pathname ,int mode )
mode:R_OK可读,W_OK可写,X_OK可执行,F_OK文件存在
判断文件是否可以进行某种操作、文件是否存在。
内核以进程的有效用户ID和有效组ID为基础执行访问权限测试,而access函数是按实际用户ID和实际组ID来进行访问权限测试。
实际用户ID是文件的性质,有效用户ID是进程的性质。
dup()和dup2() 复制文件描述符
dup家族复制文件描述符时不会复制文件表,即多个描述符对应同一张文件表。
dup()是系统选择新的描述符的值(未使用的最小值)
dup2()是程序员指定新的描述符的值,如果指定的值已经被使用,会强制关闭后继续使用。
fcntl() 函数 - 提供一些文件控制的功能,包括:
文件描述符的复制、设置或者获取文件描述符的状态、文件锁
int fcntl(intfd,int cmd,...);
参数fd就是文件描述符,cmd是命令,...代表0-n个任意类型的参数。
返回和 cmd 的选择有关
cmd 主要包括:
1. F_DUPFD- 复制文件描述符,需要传入第三个参数做新的描述符的值,如果这个值已经被使用,找 大于该值的未使用的最小值。
2. F_SETFL/F_GETFL- 设置/获取 文件描述符的状态,SETFL基本用不到,因为只能修改O_APPEND;GETFL不需要第三个参数,可以获取 权限和 O_APPEND,创建标识无法获取。
3. F_SETLK/F_SETLKW- 设置文件锁
其他的一些常用函数:(f开头的对已打开的文件操作)
chmod() 和fchmod () - 修改文件的权限
chown ()、fchown()和lchown() –更改文件的用户ID和组ID
truncate()和ftruncate() – 文件截短,即指定文件的大小。
link()和unlink()-创建硬链接和删除目录项(文件的链接计数减1,计数为0时,该文件的内容才删除,对创建的文件立即调用unlink,进程关闭该文件或终止时,文件的内容才会被删除。
remove() - 删除文件或者 空目录,功能分别与unlink和rmdir相同。
rename() - 文件或者 目录 改名。
symlink()和readlink()-创建和打开符号链接。
库函数访问文件
FILE *fopen (const char *filename,const char * mode )
常见打开模式:r,rb w,wb a,ab r+,r+b,rb+ w,w+b,wh+ a+,a+b,ab+
b用于在windows中区分二进制文件和文本文件在,linux中不区分。
int fclose(FILE *fp) 关闭一个流
Size_t fread (void *ptr, size_t size , size_t n, FILE *stream )
Size_t fwrite (const void *ptr, size_t size, size_t n, FILE *stream )
int fgetc(FIEL*stream) 从指定文件读取一个字符
int fputc (intc,FILE *stream )向指定文件写入一个字符
fscanf (FILE*stream ,char * formate[,argument ….]
从一个流中进行格式化输入
int fprintf (FILE*stream ,char *formate[,argument…])
格式化输出到一个流中
int fseek(FILE*stream ,long offset ,int whence )
文件定位
int ftell(FILE * fp) 返回当前文件位置
标C中要用fseek()+ftell()获取文件的大小。
其它常用函数
int rewind(FILE *fp) 将一个流设置到文件的起始位置。
int ferror(FILE *fp) 判断一个流是否出错。
int feof(FILE *fp) 判断是否到达文件尾(这个函数需谨慎使用)。
int fileno(FILE *fp) 文件指针转换为文件描述符。
char *tmpnam(char *ptr)
FILE *tmpfile(void) 这两个函数创建临时文件。
int fflush(FILE *fp) 强制冲洗一个流。
当流涉及终端时,通常使用行缓冲。行缓冲在缓冲区满时或者有换行符\n,冲洗缓冲区,标C不对字符进行缓冲,标准出错是不带缓冲的。
UC函数在用户层没有输入输出的缓冲区,而标C函数有缓冲区。UC函数写一次就访问一次内核;标C函数先放入缓冲区,等缓冲区满了再访问一次内核。但UC函数可以 由 程序员自定义缓冲区,从而大幅 提升效率。
标C可以使用以下两个函数更改和设定缓冲区大小:
void setbuf(FILE *fp,char * buf)
int setvbuf (FILE *fp,char *buf, intmode , size_t size )