Linux文件IO

Linux文件IO 文件IOLinux内核向应用层提供的文件操作方法属于Linux系统调用打开文件 open读写文件 read/write关闭文件 close函数接口openint 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 创建 O_APPEND 追加 O_TRUNC 清空 r O_RDONLY r O_RDWR w O_WRONLY | O_CREAT | O_TRUNC w O_RDWR | O_CREAT | O_TRUNC a O_WRONLY | O_CREAT | O_APPEND a O_RDWR | O_CREAT | O_APPEND mode 当前用户、同组用户、其他人对文件的读写执行权限 *当flags标志位中存在O_CREAT方式则必须增加mode参数 111 111 111 -----0777 mode ~umask 注意创建普通文件时mode给到0664足够 返回值 成功文件描述符 失败-1文件描述符小的非负的整形数据1024个0-1023操作系统为已打开的文件分配的一个标识符。分配原则最小未被使用原则文件IO操作文件面向文件描述符。操作系统默认已经打开了三个文件标准输入设备、标准输出设备、标准出错设备 文件描述符fd 文件流指针FILE* 标准输入设备 ----》0 ---------》stdin 标准输出设备 ----》1 ---------》stdout 标准出错设备 ----》2 ---------》stderrcloseint close(int fd); 功能关闭文件 注意对于打开的文件使用完时要及时关闭。 由于文件描述符个数有限光打开文件不关闭会造成文件描述符泄露。writessize_t write(int fd, const void *buf, size_t count); 功能向文件中写入数据 参数 fd要写的文件的文件描述符 buf要写入的数据首地址 count要写入的字节数 返回值 成功返回实际写入的字节数 失败-1//为方便操作此处把声明都放在了本“head.h”中 #ifndef __HEAD_H__ #define __HEAD_H__ #include stdio.h #include sys/fcntl.h #include sys/types.h #include sys/stat.h #include unistd.h #include string.h #endif#include head.h int main(int argc, const char *argv[]) { int fd open(1.txt, O_WRONLY | O_CREAT | O_TRUNC, 0664); if (fd 0) { printf(open error\n); return -1; } int cnt 100; char str[] {how are you}; ssize_t size write(fd, hello world, strlen(hello world)); printf(size %ld\n, size); write(fd, str, strlen(str)); write(fd, cnt, sizeof(int)); close(fd); return 0; }readssize_t read(int fd, void *buf, size_t count); 功能从文件中读数据 参数 fd文件描述符 buf存储数据的空间首地址 count期望读到的字节数 返回值 成功返回实际读到的字节数 失败-1 到达文件末尾0#include head.h int main(int argc, const char *argv[]) { int fd open(1.txt, O_RDONLY); if (fd 0) { printf(open error\n); return -1; } char buff[512] {0}; ssize_t size read(fd, buff, sizeof(buff)); printf(size %ld, buff %s\n, size, buff); size read(fd, buff, sizeof(buff)); printf(size %ld, buff %s\n, size, buff); close(fd); return 0; }练习使用文件IO实现cat功能 #include stddef.h #include head.h int main(int argc, char **argv) { int fd open(01_open.c, O_RDONLY); if (fd 0) { printf(open error\n); return -1; } char buff[512] {0}; while (1) { size_t size read(fd, buff, sizeof(buff)); if (size 0) { break; } write(1, buff, size); // printf(%s\n, buff); } close(fd); return 0; }练习使用文件IO实现文件的拷贝 #include head.h int main(int argc, char **argv) { int fd open(argv[1], O_RDONLY); int fd2 open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0664); if (fd 0 || fd2 0) { printf(open error\n); return -1; } char buff[512] {0}; while (1) { size_t size read(fd, buff, sizeof(buff)); if (size 0) { break; } write(fd2, buff, size); } close(fd2); close(fd); return 0; }文件位置定位函数off_t lseek(int fd, off_t offset, int whence); 功能文件读写位置偏移和定位 参数 fd需要重定位的文件 offset偏移量字节 whence要偏移的起始位置 SEEK_SET :文件开头 SEEK_CUR :文件当前读写位置 SEEK_END 文件末尾 返回值 成功返回偏移后的位置到文件开头的偏移量 失败-1 求文件大小len off_t len lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); //复位#include head.h #include stdio.h int main(int argc, char **argv) { int fdopen(1.txt,O_WRONLY|O_CREAT|O_TRUNC,0664); if(fd0) { printf(open error\n); return -1; } off_t offsetlseek(fd,5,SEEK_SET); write(fd,A,1); printf(offset is %ld\n,offset); offsetlseek(fd,5,SEEK_CUR); write(fd,B,1); printf(offset is %ld\n,offset); //求文件的大小 offsetlseek(fd,0,SEEK_END); lseek(fd,0,SEEK_SET); printf(size is %ld\n,offset); close(fd); return 0; }文件IO和标准IO的区别文件IO面向文件描述符fd由Linux内核提供属于系统调用跨平台可移植性弱无缓冲区所以可以用在对硬件的控制上可以操作普通文件也可以操作硬件相关的设备类文件管道套接字等标准IO面向文件流指针FILE *C标准库函数跨平台可移植性强有缓冲区实现数据缓存避免频繁进行用户空间和内核空间切换带来的时间消耗主要使用在对普通文件-的读写上文本文件操作居多缓冲区高速设备和低速设备进行交互时为了匹配低速设备的速率需要在高速设备和低速设备之间增加一个缓冲区用于数据缓存。比如队列行缓冲1k字节 terminal主要用于人机交互--- stdout ---终端。缓存区满或者遇到\n刷新行缓存多是关于终端的一些操作遇到 \n刷新缓存区满刷新程序结束刷新fflush刷新 fflush(stdout); //强制刷新全缓冲4k主要用于文件的读写 --- 普通文件的操作缓存区满刷新缓存区对普通文件进行标准IO操作建立的缓存一般为全缓存缓存区满刷新程序结束刷新fflush来刷新 fflush(fp);文件关闭刷新无缓冲0k 主要用于出错处理信息的输出 stderr不对数据缓存直接刷新printf();stdoutfprintf(strerr,fopen error %s,filename);界面交互 出错处理出错处理相关函数errno全局的错误码变量程序运行过程中会将对应的函数调用出错信息保存在这个变量中。strerror函数char *strerror(int errnum); 功能将错误码装换成对应的错误信息以字符串方式返回 参数 errnum错误码 返回值 返回错误码对应的错误描述信息perror函数void perror(const char *s); 功能打印出错信息和出错原因 参数 s自定义的错误信息error函数void error(int status, int errnum, const char *format, ...); 功能打印自定义的错误信息 error(1, errno, %s : %s : %d :open error: aaa, __FILE__, __func__, __LINE__); 参数 status状态值 0 SUCCESS 1FAIL errnum错误码errno format格式化后错误信息字符串 c语言内置宏 __FILE__ 表示是那个文件 __LINE__ 表示第几行 __func__ 表示在那个函数 // __FUNCTION__ __DATE__ 日期此处将三个函数分别调用读者可自行实操观察三个函数有何不同 #include errno.h #include error.h #include head.h int main(int argc, char **argv) { int fd open(aaa, O_RDONLY); if (fd 0) { // printf(open error:%s\n,strerror(errno)); perror(open error); //error(1, errno, %s : %s : %d:open error:aaa, __FILE__, __func__, __LINE__); //return -1; } return 0; }目录操作打开目录 opendir读目录 readdir关闭目录 closediropendir函数DIR *opendir(const char *name); 功能打开一个目录并获得一个目录流指针 参数 name目录名 返回值 成功目录流指针 失败NULL struct dirent *readdir(DIR *dirp); 功能读取目录中的文件信息 参数 dirp目录流指针 返回值 成功返回文件信息的结构体指针 失败NULL int closedir(DIR *dirp); 功能关闭一个目录流返回的结构体指针所指的结构体中包含如图所示信息#include head.h #include dirent.h int main(int argc, char **argv) { DIR* pdiropendir(..); if(NULL pdir) { perror(opendir error); return -1; } while(1) { struct dirent* pinfreaddir(pdir); if(NULL pinf) { break; } if(. pinf-d_name[0]) { continue; } printf(%ld %s\n,pinf-d_ino,pinf-d_name); } closedir(pdir); return 0; }mkdir函数int mkdir(const char *pathname, mode_t mode); 功能创建一个目录 参数 pathname目录名 mode对目录的读写执行权限 0777 返回值 成功0 失败-1 char *getcwd(char *buf, size_t size); 功能获取当前工作路径 参数 buf 存储当前路径的空间 size空间大小 返回值 成功buf的首地址 失败NULL int chdir(const char *path); 功能修改当前工作路径 参数 path新的工作路径 返回值 成功0 失败-1#include head.h int main(int argc, char **argv) { int retmkdir(dir,0777); if(ret0) { perror(mkdir error); return -1; } return 0; }#include head.h int main(int argc, char **argv) { char path[128]{0}; getcwd(path,sizeof(path)); printf(path:%s\n,path); chdir(..); mkdir(ccc,0777); getcwd(path,sizeof(path)); printf(path:%s\n,path); return 0; }chmod 八进制值 文件名 ---修改该文件的读写执行权限 chmod 0777 1.txt pwd 获取当前目录对应的绝对路径时间相关函数包括time函数ctime函数localtime函数time_t time(time_t *tloc); 功能获取1970-1-1 000到现在的秒数 参数 tloc保存秒数的变量地址 返回值 返回秒数 char *ctime(const time_t *timep); 功能将秒数转换成字符串时间 参数 timep秒数的地址 返回值 返回时间字符串 struct tm *localtime(const time_t *timep); 功能将秒数转换成日历时间 参数 timep秒数的地址 返回值 返回具体时间的结构体指针返回的结构体指针所指的结构体中包含如下所示信息struct tm { int tm_sec; /* Seconds (0-60) */ int tm_min; /* Minutes (0-59) */ int tm_hour; /* Hours (0-23) */ int tm_mday; /* Day of the month (1-31) */ int tm_mon; /* Month (0-11) */ int tm_year; /* Year - 1900 */ int tm_wday; /* Day of the week (0-6, Sunday 0) */ int tm_yday; /* Day in the year (0-365, 1 Jan 0) */ int tm_isdst; /* Daylight saving time */ };#include head.h #include time.h int main(int argc, char **argv) { time_t sec; time(sec); printf(sec is %ld\n,sec); char* ptimectime(sec); printf(ptime:%s\n,ptime); struct tm *ptlocaltime(sec); printf(%d-%02d-%02d %02d:%02d:%02d\n,pt-tm_year1900,pt-tm_mon1, pt-tm_mday,pt-tm_hour,pt-tm_min,pt-tm_sec); return 0; }