企业网站 设计国外网站建设
目录
一、文件IO
1.1 文件IO的概念
1.2 什么是文件描述符
1.3 特殊的文件描述符
1.4 文件IO函数
1.4.1 open
open代码示例
1.4.2 umask
1.4.3 close
1.4.4 write
write代码示例
1.4.5 read
read代码示例
1.4.6 lseek
lseek的代码示例
二、获取文件信息
2.1 stat
2.2 获取文件所属用户 getpwuid
2.3 获取文件所属组名getgrgid
2.4 获取文件类型和权限
三、目录相关函数
3.1 opendir
3.2 closedir
3.3 readdir
opendir| closedir|readdir代码示例
四、练习
4.1 使用文件IO读取图片 文件大小、文件偏移量,宽度,高度
4.2 向一个程序中输入文件名,判断指定目录下是否有这个文件,如果有这个文件,将这个文件的属性信息输出。如果不存在输出不存在即可。
一、文件IO
1.1 文件IO的概念
文件IO:指程序和文件系统之间的数据交互
特点:
1.不存在缓冲区,访问速度慢
2.不可以移植,依赖于操作系统
3.可以访问不同的文件类型(软连接,块设备等)
4.文件IO属于系统调用
5.文件IO在操作文件时使用文件描述符
1.2 什么是文件描述符
当操作一个文件的时候,则需要创建并打开一个文件,系统就会给文件分配一个编号,这个编号就是文件描述符
文件描述符本质就是数组的下表,标准IO是对文件IO的二次封装,所以FILE结构体里面存在文件描述符int _fileno;
1.文件描述符:文件描述符的本质就是数组的下表,默认共有1024个文件描述符,范围[0-1023]
ulimit -a 查看文件描述符的总个数
修改文件描述符的个数(修改只对当前终端有效)
ulimit -n 个数 ---》ulimit -n 2048
2.文件描述符的申请规则:分配从小到大,未申请的文件描述符
举例:申请4个文件,则文件描述符 3 4 5 6,关闭4文件描述符,重新申请则文件描述符是最小的编号4
3.因为文件描述符的个数有限,所以在不适用的情况下,需要关闭
4.查看中的文件描述符的个数函数
功能:查看文件描述符的总个数
格式:#include <unistd.h>int getdtablesize(void);
返回值:返回文件描述符的总个数
1.3 特殊的文件描述符
stdin--->0
stdout--->1
stderr--->2
1.4 文件IO函数
open close write read lseek
1.4.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);函数格式:int open(const char *pathname, int flags, ...);
参数:pathname:指定打开文件的路径以及文件名flags:必须包含以下三个之一O_RDONLY 只读O_WRONLY, 只写O_RDWR 读写——————————————————————此外,还可以添加以下选项,注意需要使用安位或链接O_APPEND 追加O_CREAT 创建O_TRUNC 清空————————————————————————————————eg: 表示标准IO中的w权限"w": ----> O_WRONLY | O_CREAT| O_TRUNC#define O_WRONLY 00000001#define O_CREAT 00000100#define O_TRUNC 00001000_________________________________00001101 ---->保留所有权限 mode:可有可无mode是由 flags中的O_CREAT 决定的如果flags指定O_CREAT,则mode不可以忽略,需要写创建文件权限 eg:0664 0777如果flags没有指定O_CREAT,则mode可以忽略如果flags指定O_CREAT,并且文件已经创建,则mode不起效果 mode指定权限,但是实际的权限是(mode & ~umask)
返回值:成功返回新的文件描述符失败返回-1,跟新errno_______________________________
eg: 使用文件io函数以w的方式打开open("./one.txt",O_WRONLY | O_CREAT| O_TRUNC,0777) open("./one.txt",O_RDONLY )
open代码示例
1.4.2 umask
1.什么是umask
umask是文件权掩码
2.查看文件权限掩码umask
umask
3.修改文件权限掩码
1.shell指令(只对当前终端有效)
umask 修改的值 ---->umask 0
2.使用函数实现修改文件权限掩码(只对当前终端有效)
#include <sys/stat.h>mode_t umask(mode_t cmask);
功能:修改文件权限掩码
参数:cmask 修改权限掩码的值
返回值:返回上一个权限掩码值,如果是第一次修改则返回0
eg: umask(0)
1.4.3 close
格式#include <unistd.h>int close(int fd);
功能:通过文件描述符关闭文件
参数:int fd: open函数打开的文件描述符
返回值:成功返回0,失败返回-1,跟新errno
1.4.4 write
功能:把数据转换为二进制文件,写入到文件中,在文件中以字符的形式展示
格式:#include <unistd.h>ssize_t write(int fd, const void *buf, size_t count);
参数:int fd: 文件描述符void *buf: 写入内容的首地址count: 写入的字节大小
返回值:成功返回写入的字节数,失败返回-1,跟新errno
write代码示例
1.4.5 read
功能:根据文件描述符实现文件读取
格式:#include <unistd.h>ssize_t read(int fd, void *buf, size_t count);
参数:fd: 文件描述符buf:存储读取的内容count: 读取的字节大小
返回值:成功返回读取的字符读取到文件结尾,则返回0如果读取失败返回-1,跟新errno
read代码示例
1.4.6 lseek
功能:文件指针的偏移(修改光标所在位置)格式:#include <sys/types.h>#include <unistd.h>off_t lseek(int fd, off_t offset, int whence);
参数:fd: 文件描述符offset: 指针的偏移量,如果offset>0 ,指针向后偏移如果offset<0 指针向前偏移offset=0 指针不偏移whence:SEEK_SET 把光标设置在起始位置SEEK_CUR 把光标设置在当前位置SEEK_END 把光标设置在结尾位置整个光标的位置 offset+whence 返回值:成功返回起始到当前位置的偏移量失败返回-1,跟新errno—————————————————————————————————————————————————————— eg:把文件IO的光标偏移到文件的起始位置lseek(fd,0,SEEK_SET) 返回值0 lseek(fd,10,SEEK_SET) 返回值10 起始位置到当前偏移后的指针的字节大小eg:计算文件大小lseek(fd,0,SEEK_END) 起始位置到结尾的字节大小(文件大小 )
lseek的代码示例
二、获取文件信息
2.1 stat
功能:获取文件信息(文件类型 文件权限 硬链接数, 用户名 文件所属组, 时间)不可以获取软链接文件信息,可以使用lstat函数格式:#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>int stat(const char *pathname, struct stat *statbuf);
参数:pathname:查看文件对应的路径以及文件名struct stat statbuf: 文件的所有信息struct stat {dev_t st_dev; /* ID of device containing file */ino_t st_ino; /* Inode number */ inode号mode_t st_mode; /* File type and mode */ 文件类型和权限nlink_t st_nlink; /* Number of hard links */ 硬链接数uid_t st_uid; /* User ID of owner */ uid用户idgid_t st_gid; /* Group ID of owner */ gid组iddev_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 nanosecondprecision 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 最后一次访问的时间(秒)#define st_mtime st_mtim.tv_sec 最后一次修改的时间(秒)#define st_ctime st_ctim.tv_sec 最后一次状态修改的时间(秒)};返回值:成功返回0,失败返回-1 跟新errno
2.2 获取文件所属用户 getpwuid
功能:根据用户id获取用户对应的信息
格式:#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 */};成功返回strutc passwd类型的指针,存储用户的相关信息失败返回NULL 跟新errno
2.3 获取文件所属组名getgrgid
功能:根据组id,获取组对应的信息
格式:#include <sys/types.h>#include <grp.h>struct group *getgrgid(gid_t gid);
参数:gid: 组id
返回值 成功返回指向组对应信息的结构体指针失败返回NULL,跟新errno 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 pointersto names of group members */};
2.4 获取文件类型和权限
文件类型是由st_mode的高4位决定
权限是由st_mode的第9位决定的
man 7 inode
———————————————————————文件类型—————————————————————————方式1:switch(st.st_mode& S_IFMT){case S_IFSOCK:printf("socket");break;case S_IFLNK:printf("symbolic");break;case S_IFREG:printf("regular");break;case S_IFBLK:printf("block");break;case S_IFDIR:printf("directory");break;case S_IFCHR:printf("character");break;case S_IFIFO:printf("FIFO");break;}
方式2:if( S_ISREG(st.st_mode))printf("regular");else if( S_ISDIR(st.st_mode))printf("directory?");else if( S_ISCHR(st.st_mode))printf("character");else if( S_ISBLK(st.st_mode))printf("block");else if( S_ISFIFO(st.st_mode))printf("FIFO");else if( S_ISLNK(st.st_mode))printf("symbolic");else if( S_ISSOCK(st.st_mode)) printf("socket");————————————————————————文件权限—————————————————————————
/获取文件权限printf("mode=%#o\n",st.st_mode&0777);
三、目录相关函数
3.1 opendir
功能:打开指定路径下目录
格式:#include <sys/types.h>#include <dirent.h>DIR *opendir(const char *name);
参数:name: 打开的目录以及路径
返回值:成功返回目录的流指针,失败返回NULL,跟新errno
3.2 closedir
功能:关闭目录流指针
格式#include <sys/types.h>#include <dirent.h>int closedir(DIR *dirp);
参数:dirp: 目录流指针 就只opendir返回的指针返回值:成功返回0 失败返回-1 跟新errno
3.3 readdir
功能:读取目录对应的信息格式:#include <dirent.h>struct dirent *readdir(DIR *dirp);
参数:dirp: 目录流指针 就只opendir返回的指针
返回值:struct dirent {ino_t d_ino; /* Inode number */ inode号off_t d_off; /* Not an offset; see below */unsigned short d_reclen; /* Length of this record */ 结构体的大小会睡着d_name的实际长度改变而改变unsigned char d_type; /* Type of file; not supported 类型by all filesystem types */char d_name[256]; /* Null-terminated filename */ 名字};如果成功,则返回一个struct dirent类型的结构体,结构体中存储目录的相关信息如果遇到文件结尾,返回NULL,不更新errno如果读取失败,则返回NULL,跟新errno
opendir| closedir|readdir代码示例
四、练习
4.1 使用文件IO读取图片 文件大小、文件偏移量,宽度,高度
1.bmp文件头(bmp file header):提供文件的格式、大小等信息 (14字节)
2 位图信息头(bitmap information):提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息(40字节)
3.位图数据(bitmap data):就是图像数据啦
#include "head.h"
int main(int argc, const char *argv[])
{int fd=open("./xiaoxin.bmp",O_RDONLY);lseek(fd,2,SEEK_SET);int size;read(fd,&size,4);printf("大小:%dB\n",size);lseek(fd,10,SEEK_SET);int offset;read(fd,&offset,4);printf("偏移量:%d\n",offset);lseek(fd,18,SEEK_SET);int width;read(fd,&width,4);printf("宽度:%d\n",width);lseek(fd,22,SEEK_SET);int high;read(fd,&high,4);printf("高度:%d\n",high);close(fd);return 0;
}
4.2 向一个程序中输入文件名,判断指定目录下是否有这个文件,如果有这个文件,将这个文件的属性信息输出。如果不存在输出不存在即可。
./a.out 目录名 查询的文件名
argv[1] argv[2]
#include "head.h"
int main(int argc, const char *argv[])
{// 检查文件是否存在DIR *dp=opendir(argv[1]);if(dp==NULL){printf("目录不存在\n");return 0;}struct dirent *f=NULL;while( f=readdir(dp) ){if(strcmp(f->d_name,argv[2])==0)break;}if(f==NULL){printf("文件不存在");return 0;}closedir(dp);// 打印文件相关信息// 获取文件相对路径char file[128];sprintf(file,"%s/%s",argv[1],argv[2]);struct stat st;if(stat(file,&st)==-1)PRINTF_ERROR("stat error");// 获取文件权限// 获取文件类型mode_t mode=st.st_mode;switch(mode&0170000){case 0010000:printf("p");break;case 002000:printf("c");break;case 0040000:printf("d");break;case 0060000:printf("b");break;case 0100000:printf("-");break;case 0120000:printf("l");break;case 0140000:printf("s");break;default:printf("error\n");break;}int chown=mode&0777;printf("%#o ",chown);// 获取硬链接数int num=st.st_nlink;printf("%d ",num);// 获取用户idint id=st.st_uid;// 获取用户名struct passwd *p=getpwuid(id);printf("%s ",p->pw_name);// 获取组idgid_t gid=st.st_gid;// 获取组名struct group *gr=getgrgid(gid);printf("%s ",gr->gr_name);// 获取文件大小off_t size=st.st_size;printf("%ld ",size);// 获取文件idino_t fid=st.st_ino;// 获取最后一次访问的时间转换为年月日时分秒struct tm *t=localtime(&st.st_atim.tv_sec);printf("%d-%d-%d %02d:%02d:%02d ",t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);// 输出文件名printf("%s\n",argv[2]);return 0;
}