一、文件IO
1、文件io通过系统调用来操作文件
系统调用:系统提供给用户的一组API(接口函数)
open/read/write/close/lseek...
用户空间进程访问内核的接口
把用户从底层的硬件编程中解放出来
极大的提高了系统的安全性
使用户程序具有可移植性(同一系统下)
是操作系统的一部分
文件io没有缓存区概念
文件io操作文件的方式:通过文件描述符
shell默认打开了三个文件:
标准输入 标准输出 标准错误
stdin stdout stderr 用流来表示
0 1 2 用文件描述符表示
2、文件IO相关函数
1、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);
参数
pathname:文件的路径
flags:文件打开的方式
O_RDONLY:只读
O_WRONLY:只写
O_RDWR:可读可写
这三个宏互斥(三选一)
O_CREAT:如果文件不存在,则创建文件,此时用到open函数的第二种形式。
O_TRUNC:如果文件存在则清空文件的内容。
O_APPEND:以追加的方式打开文件。
mode:文件的权限,八进制(0777)
返回值
成功返回一个新的文件描述符,失败返回(-1)并设置错误号。
2、close函数
作用:
关闭文件
头文件
#include <unistd.h>
函数原型
int close(int fd);
参数
想要关闭的文件描述符
返回值
成功返回0,失败返回(-1)并设置错误号。
3、read/write
1、read
作用:
向文件读取内容
头文件:
#include <unistd.h>
函数原型
ssize_t read(int fd, void *buf, size_t count);
参数
fd:想要操作的文件描述符
buf:读取到的内容放到哪个地址
count:读取到的文件中的字符数量
返回值:
成功返回已经读取到的字节数,失败返回-1并设置错误号,读取到文件末尾返回0。
2、write
作用:
向文件写入内容
头文件:
#include <unistd.h>
函数原型
ssize_t write(int fd, void *buf, size_t count);
参数
fd:想要写入的文件描述符
buf:需要写入文件的内容
count:写入文件中字符数量
返回值:
成功返回已经写入的字节数,失败返回-1并设置错误号。
4、lseek
作用:
偏移文件内的书签
头文件:
#include <sys/types.h>
函数原型
off_t lseek(int fd, off_t offset, int whence);
参数
fd:想要写入的文件描述符
offset:偏移量,正数表示后偏移,负数前偏移,0不偏移
whence:书签偏移的起始位置
SEEK_SET:文件头
SEEK_CUR:当前位置
SEEK_END:文件末尾
返回值:
成功返回当前偏移到的位置,失败返回-1并设置错误号。
二、文件和目录
1、stat
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *pathname, struct stat *statbuf);
int fstat(int fd, struct stat *statbuf);
int lstat(const char *pathname, struct stat *statbuf);
stat,lstat通过传入的pathname获取文件属性
fstat通过用open打开的文件的文件描述符获取文件属性
stat在操作软链接文件时会获取源文件的相关属性
lstat在操作软链接文件时会获取链接文件的相关属性
成功返回0,失败返回-1,并设置错误号
相关结构体
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* Inode number */
mode_t st_mode; /* File type and mode */
nlink_t st_nlink; /* Number of hard links */
uid_t st_uid; /* User ID of owner */
gid_t st_gid; /* Group ID of owner */
dev_t st_rdev; /* Device ID (if special file) */
off_t st_size; /* Total size, in bytes */
blksize_t st_blksize; /* Block size for filesystem I/O */
blkcnt_t st_blocks; /* Number of 512B blocks allocated */
/* Since Linux 2.6, the kernel supports nanosecond
precision for the following timestamp fields.
For the details before Linux 2.6, see NOTES. */
struct timespec st_atim; /* Time of last access */
struct timespec st_mtim; /* Time of last modification */
struct timespec st_ctim; /* Time of last status change */
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
1、文件类型(可以用以下的宏确定文件类型,这些宏的参数都是struct stat结构中的ts_mode成员)
S_ISREG(m) is it a regular file?
S_ISDIR(m) directory?
S_ISCHR(m) character device?
S_ISBLK(m) block device?
S_ISFIFO(m) FIFO (named pipe)?
S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.)
S_ISSOCK(m) socket? (Not in POSIX.1-1996.)
2、文件权限
存放在st_mode低9位,从高位到低位分别表示用户权限、同组用户权限、其它用户权限,该位为1表示有权限,0表示没有权限
3、链接数
直接通过st_nlink得到
4、文件所有者
getpwuid函数相关操作得到
5、文件所属组
getgrgid函数相关操作得到
6、文件字节大小
直接通过st_size得到
7、文件更新时间
ctime(&st_ctime)得到文件的更新时间
#include <stdio.h>
#include <sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<string.h>
#include<pwd.h>
#include<grp.h>
#include<time.h>
int main(int argc, char *argv[])
{if(2!=argc){printf("error\n");}struct stat st;lstat(argv[1],&st);if(S_ISREG(st.st_mode))printf("-");else if (S_ISDIR(st.st_mode))printf("d");else if(S_ISLNK(st.st_mode))printf("l");int i=8;for ( ; i >= 0; i-=3){if(st.st_mode&1<<i!=0)printf("r");elseprintf("-");if(st.st_mode&1<<(i-1)!=0)printf("w");elseprintf("-");if(st.st_mode&1<<(i-2)!=0)printf("x");elseprintf("-");}
//用户名struct passwd *pw=getpwuid(st.st_uid);
//链接数
printf(" %ld",st.st_nlink);printf(" %s ",pw->pw_name);
struct group *gr =getgrgid(st.st_gid);
//用户组名
printf( "%s",gr->gr_name);
//长度
printf(" %ld",st.st_size);char arr[100]={0};
//获取时间strcpy(arr,ctime(&st.st_mtime));if(arr[strlen(arr)-1]=='\n')arr[strlen(arr)-1]='\0';printf(" %s ",arr);puts("");return 0;}
2、目录文件函数
1、opendir
作用:
打开一个目录文件
头文件
#include<sys/types.h>
#include<dirent.h>
函数原型:
DIR *opendir(const char *name)
参数:
name:目录文件
返回值:
成功返回目录流指针,失败返回 NULL并设置错误号。
2、readdir
作用:
读取目录当中一个文件的属性
头文件:
dirent.h
函数文件
struct dirent *readdir(DIR * dirp);
参数:
dirp:想要操作的目录流指针
返回值:
成功返回读取到的文件的相关信息的地址,被保存在一个struct dirent结构体中,失败或者读完了所有文件的返回NULL。
相关结构体:
struct dirent {
ino_t d_ino; /* Inode number */
off_t d_off; /* Not an offset; see below */
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]; /* Null-terminated filename */
};
3、closedir
作用:
关闭目录流指针
头文件:
#include <sys/types.h>
#include <dirent.h>
函数原型:
int closedir(DIR *dirp);
参数:
dirp:目录流指针
返回值:
成功返回0,失败返回-1并设置错误号