Liunx C 语言-文件编程

  • Post author:
  • Post category:其他




Liunx C 语言文件编程

打开创建文档->编辑文档->保存文档->关闭文档

操作系统提供了一系列的API:

打开 open 、

读写 write/read、

光标定位 lseek、

关闭 close

以上均为系统IO,操作文件是无缓存的



一 . 打开 / 创建文件



1 . 涉及函数

【打开/创建api】

相关头文件
	#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:
		要打开的文件名(含路径,缺省为当前路径, 缺省示例:./file代表当前路径下的file文件 )
	flags:
		O_RDONLY 只读打开
		O_WRONLY 只写打开
		O_RDWR 可读可写打开
	下列为可配置选项
		O_CREAT 若文件不存在则创建它,在使用此选项时,需要同时说明第三个参数mode,用其来说明该新文件的存取许可权限
		O_EXCL 和O_CREAT同时指定时,但如果文件存在则出错
		O_APPEND 每次写时都加在文件的尾端
		O_TRUNC 如果这个文件中本来是有内容的,而且为只读或只写成功打开,则将其长度截短为0
	
	mode:
	一定是在flags中使用了O_CREAT标志才需要设置mode,mode记录待创建文件的访问权限0600为可读可写 ,4可读 2可写 1可执行 所以0600为可读可写权限

返回值:成功返回文件描述符fd(非负整数),失败返回-1
----------------------------------------------------------------------------------------

【创建文件api】

相关头文件
	#include <sys/types.h>
	#include <sys/stat.h>
	#include <fcntl.h>

函数含义: 创建文件
	int creat(const char *pathname, mode_t mode);
	
参数解释:
	pathname:
		要打开的文件名(含路径,缺省为当前路径,缺省示例:./file代表当前路径下的file文件)
	mode:
		S_IRUSR 可读
		S_IWUSR 可写
		S_IXUSR 可执行
		S_IRWXU 可读可写可执行

返回值:成功返回文件描述符(非负整数),失败返回-1



2 . 示例代码



2-1 文件打开
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(){
	int ds = -1 ; 
	ds = open("./test.txt",O_RDWR);
	if(ds != -1 ){
		printf("file test.txt open success ! \r\n");
	}else{
		printf("file test.txt open fail !\r\n");
	}
	return 0 ; 
}



2-2 文件创建与打开
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

// 文件打开失败就创建文件,文件权限为 4 + 2 可读可写 
int main(){
	int ds = -1 ; 
	// 文件打开失败就创建文件,文件权限为 4 + 2 可读可写 
	ds = open("./new.txt",O_RDWR|O_CREAT,0600);
	if(ds == -1 ){
		ds = open("./new.txt",O_RDWR);
		if(ds != -1 ){
			printf("file test.txt open success 2  ! \r\n");
		}else{
			printf("file test.txt open fail ! \r\n");
		}
	}else{
		printf("file test.txt open suc 1  ! \r\n");
	}
	return 0 ; 
}


2-3 文件创建
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

int main(){
	int ds =  creat("./creat.txt",0600);
	if(ds != -1  ){
		printf("creat file success ! \r\n");
	}
	return 0 ; 
}



二 . 文件的写入与读取



1. 涉及函数

写入文件

头文件:
	#include <unistd.h>

函数含义: 向文件中写入数据
	ssize_t write(int fd,const void *buf,size_t count);

参数解释:
	fd:文件描述符,由open()creat()函数获得
	buf:写入的数据的头指针
	count:写入数据的数量
	
返回值:成功返回写入数据的数量,失败返回-1
-------------------------------------------------------------------------------------

读取文件

头文件:
	#include <unistd.h>

函数含义:向文件中读取数据
	ssize_t read(int fd, void *buf, size_t count);

参数解释:
	fd:文件描述符,由open()creat()函数获得
	buf:读取出来的数据放入该指针
	count:读取数据的数量
	
返回值:成功返回读取数据的数量,失败返回-1



2. 示例代码



2-1. 文件写入
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main(int num , char *args[]){
	// 参数判断
	if(num < 2){
		printf("number is not tow \r\n");
		return -1 ;
	}
	char *msg = "hello world !\r\n";
	// 获得文件描述
	int ds =  open(args[1],O_RDWR|O_CREAT);
	if(ds == -1 ){
		printf("create file fail !! \r\n");
		return -1 ; 
	}else{
		printf("create file success !! \r\n");
	}
	// 写入数据
 	int ret = write(ds,msg,strlen(msg));
	if(ret != -1 ){
		printf("write data:%d  success !! \r\n",ret);
	}else{
		printf("write data fail !! \r\n");
		return -1 ;
	}
	return 0 ; 
}


2-2. 文件读取
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
	
int main(){
	int ds = open("write.txt",O_RDWR);
	if(ds == -1 ){
		printf("file not find \r\n");
		return -1 ; 
	}
	// 读取数据
	char msg[15] = {};
	// 这里先用固定长度接收
	int ret = read(ds,msg,15);
	if(ret != 0 ){
		printf("read file success !! \r\n");
		printf("data is : %s",msg);
	}else{
		printf("read file fail / no data !! \r\n");
	}
	return 0;
}



三 . 光标定位



1. 涉及函数

光标定位

头文件:
	#include <sys/types.h>
	#include <unistd.h>

函数含义:控制文件的光标
	off_t lseek(int fd, off_t offset, int whence);

参数解释:
fd:
	文件描述符,由open()creat()函数获得
offset:
	偏移值,正值向后偏移,负值向前偏移
whence:基准值
	SEEK_SET文件头
	SEEK_CUR文件当前光标
	SEEK_END文件尾
返回值:成功返回偏移了多少个单位,失败返回-1



2.代码示例



2-1. 基本使用
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>

int main(){
    int ds = open("./write.txt",O_RDWR);
	if(ds == -1 ){
		printf("error: file open fail \r\n");
		return -1 ; 
	}
	int where = lseek(ds,0,SEEK_END);
	printf("data size is %d bit \r\n",where);
	return 0 ; 
}


2-2. 配合文件读写
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(){
	char *msg = "hello this is laopi\r\n";
	int ds = open("./write.txt",O_RDWR|O_TRUNC);
	if(ds == -1 ){
		printf("file open fail \r\n");
		return -1 ;
	}
	int rwt =  write(ds,msg,strlen(msg));
	if(rwt == -1 ){
		printf("file write fail \r\n");
		return -1 ;
	}
	int rset= lseek(ds,0,SEEK_END);
	lseek(ds,0,SEEK_SET);
	if(rset == -1 ){
		printf("file lseek fail\r\n");
		return -1 ;
	}
	char *rdmsg = (char *) malloc(sizeof(char) * rset);
	int reat = read(ds,rdmsg,rset);
	if(reat == -1 ){
		printf("file read fail \r\n");
		return -1;
	}
	printf("data is :%s ,data size %d ,read data %d \r\n",rdmsg,rset,reat);
	return 0 ; 
}



四. 相关案例



1. 实现 cp 指令

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/*
	读取源文件数据
*/
int inputResFileInfo(char *filename,char **msg){

	int resfd = open(filename,O_RDWR);
	if(resfd == -1 ){
		printf("res file not find \r\n");
		return -1 ;
	}
	//
 	int resnum =lseek(resfd,0,SEEK_END);
	// 
	lseek(resfd,0,SEEK_SET);
	*msg  = (char * ) malloc(sizeof(char) * resnum );
	int rdt = read(resfd,*msg,resnum);

	//printf("read data is  %s , size is %d \r\n",*msg,resnum);
	if(rdt == -1 ){
		printf("read fail\r\n");
	}
	close(resfd);
	return resnum;
}

/*
	目标文件创建并写入数据
*/
int outputDesFileInfo(char *filename,char *msg){
	int desfd = open(filename,O_RDWR|O_CREAT|O_TRUNC,0600);
	if(desfd == -1 ){
		printf("des file not find \r\n");
		return -1 ; 
	}
	lseek(desfd,0,SEEK_SET);
	//printf("msg size %d\r\n",strlen(msg));
	int wrt = write(desfd,msg,strlen(msg));
	if(wrt == -1 ){
		printf("write fail\r\n");
		return -1 ; 
	}
	close(desfd);
	return wrt ; 
}

int main(int num , char *filename[]){
	if(num < 3 ){
		printf("arg not\r\n");
		return -1 ;
	}
	char *msg ; 
	int size =  inputResFileInfo(filename[1],&msg); 
	if(size == -1 ){
		printf("input fail \r\n");
		return -1 ;
	}
	// printf("msg is %s\r\n",msg );
	int wrt =  outputDesFileInfo(filename[2],msg);
	if(size > 0){
		printf("cp success \r\n");
	}
	return 0 ;
}



2. 配置文件修改

配置文件如下 :

path=/usr/home
name=zhangsan
data=2023/4/28

代码如下:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/*
	1. 文件打开 
	2. 文件读取 
	3. 数据查找 
	4. 数据修改
	5. 数据写入
	运行例子 : ./a.exe peizhi.txt path /usr/my 
 */
int main(int num , char *arg[]){
	if(num < 4){
		printf("error: arg fail \r\n");
		return -1 ;
	}
	/* 
		arg[1] 文件名称
		arg[2] 配置名称 
		arg[3] 配置数据
	 */
	int fd =  open(arg[1],O_RDWR);
	if(fd == -1 ){
		printf("open fail \r\n");
		return -1 ; 
	}

	int size =lseek(fd,0,SEEK_END);
	lseek(fd,0,SEEK_SET);
	char *msg = (char * ) malloc(sizeof(char) * size);

	int rdt = read(fd,msg,size);
	if(rdt == -1 ){
		printf("error: read fail\r\n");
		return -1 ; 
	}

//	printf("data is : \r\n %s\r\n",msg);
//  printf("=========================\r\n");
	// 根据回车来分割
	char *tk =  strtok(msg,"\r\n") ; 
	int i = 0 ;
	// 可以优化为动态数组 , 存储读取数据
	char *dst[10] = {};
	// 查找状态
	int start = 0 ;
	// 存储临时变量
	char *tmp = ""; 
	// 分割存储 
	while(tk != NULL){
		dst[i] = tk ;
		// 拼接查找配置 
		if(!start && strstr(tk,arg[2]) != NULL){
			// printf("find is %d\r\n",i);
			// 内存扩展方便拼接
			tmp = (char * )malloc(sizeof(char) * (strlen(arg[2]) + strlen(arg[3]) + 1 ));
			tmp = strcat(tmp,arg[2]);
			tmp = strcat(tmp,"=");
			tmp = strcat(tmp,arg[3]);
			printf("update data is %s \r\n",tmp);
			dst[i] = tmp ; 		
			start = 1 ;
		}
		tk = strtok(NULL,"\r\n");
		i++;
	}
	close(fd);
	if(!start){
		printf("error : not find config \r\n");
		return -1 ;
	}
	// 用于清除文件内容
 	fd =open(arg[1],O_RDWR | O_CREAT | O_TRUNC , 0600);
	// 写入数据
	int j = 0 ; 
	for(;j < i ;j++){
		write(fd,dst[j],strlen(dst[j]));
		write(fd,"\n",strlen("\n"));
	}
	close(fd);
	printf("done\r\n");
	return 0 ; 
}



五. 标准 C 库(fopen)



1. open 与 fopen 区别



a . 来源

open是UNIX系统调用函数(包括LINUX等),返回的是文件描述符(File Descriptor),它是文件在文件描述符表里的索引。

fopen是ANSIC标准中的C语言库函数,在不同的系统中应该调用不同的内核api。返回的是一个指向文件结构的指针。



b . 移植性


fopen

是C标准函数,因此拥有良好的移植性;


open

是UNIX系统调用,移植性有限。



c . 适用范围

open 返回文件描述符,而文件描述符是UNIX系统下的一个重要概念,UNIX下的一切设备都是以文件的形式操作。如网络套接字、硬件设备等。当然包括操作普通正规文件(Regular File)。

fopen 是用来操纵普通正规文件(Regular File)的。



d . 文件 IO 层次

如果从文件IO的角度来看,前者(open)属于低级IO函数,后者(fopen)属于高级IO函数。低级和高级的简单区分标准是:谁离系统内核更近。低级文件IO运行在内核态,高级文件IO运行在用户态。



e . 缓冲


缓冲文件系统


缓冲文件系统的特点是:在内存开辟一个“缓冲区”,为程序中的每一个文件使用;当执行读文件的操作时,从磁盘文件将数据先读入内存“缓冲区”,装满后再从内存“缓冲区”依此读出需要的数据。执行写文件的操作时,先将数据写入内存“缓冲区”,待内存“缓冲区”装满后再写入文件。由此可以看出,内存“缓冲区”的大小,影响着实际操作外存的次数,内存“缓冲区”越大,则操作外存的次数就少,执行速度就快、效率高。一般来说,文件“缓冲区”的大小随机器 而定。fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind等。


非缓冲文件系统


缓冲文件系统是借助文件结构体指针来对文件进行管理,通过文件指针来对文件进行访问,既可以读写字符、字符串、格式化数据,也可以读写二进制数据。非缓冲文件系统依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出,它不设文件结构体指针,只能读写二进制文件,但效率高、速度快,由于ANSI标准不再包括非缓冲文件系统,因此建议大家最好不要选择它。open, close, read, write, getc, getchar, putc, putchar等。



2. 代码示例

相关函数

fopen,fwrite,fread,fclose,fseek (与前面类似具体可以查看菜鸟教程: https://www.runoob.com/cprogramming/c-file-io.html )
标准IO操作文件是有缓存的

文件使用方式由r,w,a,t,b,+六个字符拼成,各字符的含义是:
	r(read): 只读
	w(write): 只写
	a(append): 追加
	t(text): 文本文件,可省略不写
	b(binary): 二进制文件
	+: 读和写

示例代码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
int main()
{
    FILE *fp;
    char *str = "zhang shuai!";
    char readBuf[128]={'\0'};
    
    //FILE *fopen(const char *path, const char *mode);        
    
    fp = fopen("./peng.txt","w+");
    
    //size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
    //fwrite(str,sizeof(char),strlen(str),fp);
    
    fwrite(str,sizeof(char)*strlen(str),1,fp);
    
    //int fseek(FILE *stream, long offset, int whence);    
 
    fseek(fp,0,SEEK_SET);
 
    //size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
    
    fread(readBuf,sizeof(char),strlen(str),fp);
    
    printf("read data: %s\n",readBuf);
    
    //int fclose(FILE *fp);
    
    fclose(fp);
 
    return 0;
}

好啦liunx 文件编程就分享到这里了,如果你有什么建议或意见可以评论或私信┗|`O′|┛ 嗷~~



版权声明:本文为weixin_50239605原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。