基于Linux系统文件操作超详细版

发布时间:2026/8/14 15:56:52
基于Linux系统文件操作超详细版 一 linux系统编程1.linux系统架构1用户空间应用空间2内核空间驱动--------本质上是用来驱动硬件的软件程序操作系统------软件和硬件的大管家系统调用 ------向用户空间提供内核功能的接口以函数的的方式提供使用接口应用程序使用到内核功能完成自己的功能要使用系统调用实现应用程序两条路径1直接使用系统调用2借助第三方库来实现二 库函数文件编程如何来操作文件strace 跟踪到系统调用strace ./a.outlinux系统的七种文件类型b --------block-------- 块设备文件 ls -l /dev/sdac---------char--------- 字符设备文件 ls -l /dev/input/mouse0d ---------directory ------目录文件- ---------regular-------- 常规文件I ---------symblink -------软连接文件 eg . ln -s day1/ dirs ---------socket ---------- 套接字文件p ----------pipe ------------管道文件 mkfifo pipels -l--------------------------------------------------------------------------------1. 打开文件1.fopenFILE *fopen(const char *pathname, const char *mode)功能流打开函数打开文件打开pathname指定的一个文件并关联一个流给这个文件参数pathname 是一个文件名的字符串moder 打开文件做读操作r 对文件进行读写操作w 只写------如果文件存在则清0不存在则创建w 读写a 追加从末尾写 文件不存在则会创建a 读写读---从头读 写----从末尾写返回值成功时返回FILE *指针即FILE的地址-----流指针或文件指针FILE *fp fopen(1.txt,r);此时操作fp就相当于操作文件失败时返回NULL#includestdio.h #includefcntl.h int main(int argc, const char *argv[]) { FILE *fp fopen(1.txt,r); if(fp NULL) { printf(fopen faile); return -1; } printf(fopen success!\n); return 0; }出错信息打印函数perror(自定义字符串);输出效果 自定义字符串错误原因errno 是全局变量的一个错误码变量#includestdio.h #includefcntl.h int main(int argc, const char *argv[]) { FILE *fp fopen(1.txt,r); if(fp NULL) { // printf(fopen faile); perror(fopen faile); return -1; } printf(fopen success!\n); return 0; }出错时2.读写1 fgetcint fgetc(FILE *stream)功能单个字符输入函数参数stream 表示要进行读取的文件文件指针返回值成功 返回读到的字符字符的ASCII失败 EOF //-1到达文件末尾也返回EOFend of file系统中默认打开了三个文件标准输入 -------stdin //鼠标键盘标准输出 --------stdout //输出标准出错 --------stderr#includestdio.h int main(int argc, const char *argv[]) { int ret fgetc(stdin); printf(ret %c:%d\n,ret ,ret); return 0; }运行结果练习cat1 打开文件------FILE *fp2 fgetcfp#includestdio.h int main(int argc, const char *argv[]) { if(argc ! 2) { return -1; } FILE *fp fopen(argv[1],r); while(1) { int ret fgetc(fp); if(ret EOF) break; printf(%c,ret); } }运行结果2fcloseint fclose(FILE *stream);功能关闭流并释放相关内存空间参数 stream 要关闭的流返回值成功时返回0失败时返回EOF 并且 errno重置注意同一个文件不可以多次fclose#includestdio.h int main(int argc, const char *argv[]) { if(argc!2) //命令行参数个数 //./a.out test.txt 时argc 等于 2第1个是程序名 ./a.out第2个是文件名 test.txt { printf(Usage: %s filename\n,argv[0]); return -1; } FILE *fp fopen(argv[1],r); if(fp NULL) { perror(open fail); return -1; } while(1) { int ret fgetc(fp); if(ret EOF) break; printf(%c,ret); } fclose(fp); return 0; }结果3fputcint fputc (int c,FILE*stream)功能输出单个字符参数 c 表示要输出的字符stream 表示要输出到的文件返回值 成功返回输出的字符ASCII码值失败返回EOF#includestdio.h int main(int argc, const char *argv[]) { int ret fgetc(stdin); // printf(ret %c:%d\n,ret ,ret); fputc(ret,stderr); //出错的信息打印在stderr上 return 0; }练习cp cp 1.txt 2.txt#include stdio.h #include fcntl.h // ./a.out 1.txt 2.txt int main(int argc, const char *argv[]) { if (argc ! 3) { printf(Usage: %s src file dest file\n,argv[0]); return -1; } FILE *fp_s fopen(argv[1],r); FILE *fp_d fopen(argv[2],w); if (fp_s NULL || fp_d NULL) { perror(fopen fail); return -1; } int ret 0; while (1) { ret fgetc(fp_s); if (ret EOF) break; fputc(ret,fp_d); } fclose(fp_s); fclose(fp_d); return 0; }运行结果getc1.c 的内容被复制到了haha.c上对比两个文件 使用的命令1. vi 1.c 2.c -d //看文件的不同2. diff 1.c 2.c //看文件的不同4fgetschar *fgets(char *s,int size,FILE *stream);功能从stream中读取数据最多读取size-1个数据存放到s中参数s 保存读取结果的一块内存空间size 表示一次最多读取多少个字符stream 要读取的文件返回值成功时返回s返回NULL 到达文件结尾或失败说明fgets读取结束后在读到的最后一个字符后面会加上\0读取结束的情况1 .读取到文件末尾EOF2 .读取到\n说明\n会被保存到buffer中3 .读取到size-1个字符#includestdio.h int main(int argc, const char *argv[]) { char buf[10] {1,1,1,1,1,1,1,1,1,1}; fgets(buf,sizeof(buf),stdin); printf(buf %s\n,buf); int i 0; for(i0;i10;i) { printf(buf[%d] %c:%d\n,i,buf[i],buf[i]); } return 0; }运行结果结果说明 10是输入的换行符 0是\0y练习用fgets实现cat功能#includestdio.h int main(int argc, const char *argv[]) { if(argc ! 2) { return -1; } FILE *fp_s fopen(argv[1],r); if(fp_s NULL) { printf(open fail); return -1; } while(1) { char buf[10] {0}; char *a fgets(buf,sizeof(buf),fp_s); if(a NULL) break; printf(%s,buf); } fclose(fp_s); return 0; }运行结果5fputsint fputs(const char *s, FILE *stream);功能将字符串s写入流stream参数s 存放要写入的字符串stream 打开的流文件6fread /fwrite按二进制流的输入和输出功能读取或写入二进制数据参数ptr 保存数据一块空间size 单个元素的大小nmemb 元素的个数stream 要操作的文件返回值成功 返回读取到或写入的元素个数失败 04.定位函数1.fseekint fseek(FILE *stream,long offset,int whence)功能定位文件参数*stream ---要定位的文件offset ---文件偏移量可正可负 参考点为文件开头就不可以为负whence ---参考点SEEK_SET //表示相对于文件开头的SEEK_ CUR //相当于文件当前的SEEK_END //相对于文件末尾的偏移量返回值 成功 0失败 -1 errno会被设置egfseek(fp,0,SEEK_SET); 定位到文件开头fseek(fp,100,SEEK_SET); 从头偏移100个字节2空洞文件 --------填充的全是0 用途抢占磁盘空间创建方式1.偏移2.做一次写操作#includestdio.h int main() { FILE *fp fopen(h.txt,w); if(fp NULL) { perror(fopen fail); return -1; } fseek(fp,100,SEEK_SET); fput(A,fp); return 0; } //生成的空洞文件2ftelllong ftell(FILE *stream);3fwindvoid rewind(FILE *stream)练习fread fwrite 实现cat功能#includestdio.h int main(int argc, const char *argv[]) { if(argc ! 2) { return -1; } FILE *fp fopen(argv[1],r); if( fpNULL) { perror(open fail); return -1; } while(1) { char buf[99]; int ret fread(buf,sizeof(char),99,fp); if(ret 0) break; fwrite(buf,sizeof(char),ret,stdout); } fclose(fp); return 0; }//将三个学生信息打印到文件中再读取三个学生信息 #includestdio.h typedef struct stu { char name[20]; int sno; float score; }stu_t; int main(int argc, const char *argv[]) { stu_t s[3] {{Tom,110,99.5},{Jerry,111,89.8},{XiaoMing,112,100}}; FILE *fp fopen(stu.txt,w); if (fp NULL) { perror(fopen fail); return -1; } int ret fwrite(s,sizeof(stu_t),3,fp); printf(ret %d\n,ret); fseek(fp,0,SEEK_SET); fflush(fp); getchar(); #if 0 fclose(fp); FILE *fp1 fopen(stu.txt,r); if (fp NULL) { perror(fopen fail); return -1; } #endif fseek(fp,0,SEEK_SET); stu_t s1[3]; ret fread(s1,sizeof(stu_t),3,fp); perror(fread fail); printf(ret %d\n,ret); int i 0; for (i 0; i 3; i) { printf(name : %s\n,s1[i].name); printf(sno : %d\n,s1[i].sno); printf(score : %.2f\n,s1[i].score); } return 0; }练习用fread 和 fwrite 实现文件拷贝#includestdio.h int main(int argc, const char *argv[]) { if(argc ! 3) { return -1; } FILE *fp_s fopen(argv[1],r); FILE *fp_d fopen(argv[2],w); if( fp_s NULL || fp_d NULL) { perror(open fail); return -1; } while(1) { char buf[99]; int ret fread(buf,sizeof(char),99,fp_s); if(ret 0) break; fwrite(buf,sizeof(char),ret,fp_d); } fclose(fp_s); fclose(fp_d); return 0; }搭建一个和原文件一样大小的空洞文件再进行拷贝#includestdio.h int main(int argc, const char *argv[]) { if(argc ! 3) { return -1; } FILE *fp_s fopen(argv[1],r); FILE *fp_d fopen(argv[2],w); if( fp_s NULL || fp_d NULL) { perror(open fail); return -1; } //获取原文件大小 fseek(fp_s,0,SEEK_END); long len ftell(fp_s); //创建空洞文件 fseek(fp_d,len-1,SEEK_SET); fputc(\0,fp); getchar(); fflush(fp_d); //拷贝 rewid(fp_s); char buf[len]; fread(buf,sizeof(buf),1,fp_s); fread(buf,sizeof(buf),1,fp_d); fclose(fp_s); fclose(fp_d); return 0; }三 文件IO----系统调用1.打开1openint open(const char *pathname,int flagsint mode);功能打开一个文件获得一个文件描述符参数pathname 文件名flags必须项O_RDONLY // 只写O_WRONLY //只读O_RDWR //读写可选项O_APPENDO_CREATE //创建文件O_EXCL //和O_EXCL同时使用表示新建的文件不存在成功否则open失败O_TRUNC //内容清空mode:模式 --------对应的是文件的权限------用来指定创建文件时的权限只有flags中出现O_CREAT时用rw- rw- r-- //八进制数值表示权限110 110 100 ----------0664所属于主的权限所属组的权限其他人的权限r--read w--write x--eXcute返回值成功时返回文件描述符失败时-1 errno#includestdio.h #includefcntl.h int main(int argc, const char *argv[]) { int fd open(1.txt,O_RDONLY); if(fd0) { perror(open fail); return -1; } printf(fd %d\n,fd); return 0; }运行结果2.读写1read write#includeunistd.hssize_t read (int fd,void *buf, size_t count);ssize_t write (int fd,const void *buf, size_t count);功能 读或写参数fd 要操作的文件buf 存放数据的一块空间的地址count 一次 读 或 写 的字节数返回值成功 成功读取或写入的字节数失败 -1 error读取时返回值为0表示到达文件末尾#includestdio.h #includeunistd.h int main(int argc, const char *argv[]) { char buf[1024]; int ret read(0,buf,sizeof(buf)); //0在这里相当于stdin printf(ret %d buf %s\n,ret,buf); return 0; }运行结果#includestdio.h #includeunistd.h int main(int argc, const char *argv[]) { char buf[1024]; int ret read(0,buf,sizeof(buf)); //0在这里相当于stdin // printf(ret %d buf %s\n,ret,buf); write(1,buf,ret); //1相当于stdout return 0; }练习用read 和 write 实现cat 功能#includestdio.h #includefcntl.h #includeunistd.h int main(int argc, const char *argv[]) { if(argc ! 2) { return -1; } int fp open(argv[1],O_RDONLY); if(fp0) { perror(open fail); return -1; } char buf[1024]; int ret 0; while(1) { ret read(fp,buf,sizeof(buf)); //0在这里相当于stdin if(ret 0) break; write(1,buf,ret); //1相当于stdout } return 0; }运行结果练习用read write 实现copy功能#includestdio.h #includeunistd.h #includefcntl.h int main(int argc, const char *argv[]) { if(argc ! 3) { return -1; } int fp open(argv[1],O_RDONLY); if(fp -1) { return -1; } int fd open(argv[2],O_WRONLY|O_CREAT,0664); if(fd -1) { return -1; } while(1) { char buf[1024]; int ret read(fp,buf,sizeof(buf)); if(ret 0) break; write(fd,buf,ret); } return 0; }运行结果buchong.c 被复制到了xixi.c里面3.关闭1fclose用法就是调用 fclose(要关闭的文件名)4.定位函数1lseekoff_t lseek (int fd,off_t offset, int whence);功能文件定位参数fd 要定位的文件描述offset 偏移量whence 参考点SEEK_SETSEEK_CURSEEK_END返回值成功返回偏移量的值失败 -1 和 errno使用例子1 .定位到文件开头lseek(fd,0,SEEK_SET);2 .获取到文件大小off_t len lseek(fd,0,SEEK_END); 返回偏移量就是文件的大小3.创建空洞文件#includestdio.h #includefcntl.h #includeunistd.h int main(int argc, const char *argv[]) { if(argc ! 3) { return -1; } int fd open(argv[1],O_RDONLY); int fs open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0666); if(fd 0 || fs 0) { return -1; } //获取原文件大小 off_t len lseek(fd,0,SEEK_END); //创建空洞文件 lseek(fs,len-1,SEEK_SET); write(fs,,1); close(fd); close(fs); return 0; }使用标准IO的函数想要使用read write时fd-filenoint filemo(FILE *stream)FILE *fdopen(int fd,const char *mode)使用#includestdio.h #includefcntl.h int main(int argc, const char *argv[]) { int fd open(1.txt,O_RDONLY); if(fd 0) { return -1; } printf(fd %d\n,fd); FILE *fp fdopen(fd,r); if(fp NULL) { return -1; } return 0; }int feof (FILE *stream);检测指定文件流的“文件结束指示器”End-of-File indicator是否已被设置。int ferror(FILE *stream);检测指定文件流是否发生了“读写错误”I/O Error并检查其“错误指示器”Error indicator是否被设置。#includestdio.h #includefcntl.h int main(int argc, const char *argv[]) { int fd open(1.txt,O_RDONLY); if(fd 0) { return -1; } printf(fd %d\n,fd); FILE *fp fdopen(fd,r); if(fp NULL) { perror(fdopen fail); return -1; } char buf[100]; while(1) { char *ret fgets(buf,sizeof(buf),fp); if(ret NULL) { if(feof(fp)) { perror(fgets fail); break; }else if(ferror(fp)) { perror(fgets fail); break; } } printf(buf %s\n,buf); } return 0; }