Linux系统编程—文件

目录

一、文件编程概述

二、文件打开与创建

2.1 文件打开创建函数open原型和头文件:

2.2 open函数打开一个文件:

2.3 open函数打开文件失败创建一个文件:

2.4 查看文件是否存在:

2.5 每次写内容都到文件的尾部:

2.6 O_TRUNC打开已有内容的文件并删除所有内容:

2.7 文件创建creat函数原型和头文件:

2.8 使用creat函数创建一个文件:

三、文件写入操作编程

3.1 文件写入函数write和文件关闭函数close原型和头文件:

3.2 对文件写入内容:

四、文件读取操作编程

4.1 文件读取函数read函数原型和头文件:

4.2 使用read函数读取文件中的内容:

五、文件光标移动操作

5.1 文件光标移动函数lseek函数原型和头文件:

5.2 使用lseek函数对文件进行操作:

5.3 使用lseek函数可以的巧妙的计算文件大小:

六、文件操作原理简述

七、文件编程练手(一)实现copy指令(面试)

7.1 copy指令在Linux下的应用:  

7.2 main函数的参数:

7.3 文件编程实现copy指令:

八、文件编程练手(二)修改程序的配置文件(工作常用)

8.1 使用文件编程修改配置文件的指定内容:

8.2 字符串比较函数strstr原型和头文件:

九、写一个整数、结构体和结构体数组到文件

9.1 写一个整数到文件:

9.2 写一个结构体到文件:

9.3 写一个结构体数组到文件:

十、标准C库对文件操作引入

十一、标准C库打开创建文件读写关闭文件和光标移动

11.1 打开创建文件函数fopen函数原型和头文件:

11.2 文件写入函数fwrite函数原型和头文件:

11.3 文件读取函数fread函数原型和头文件:

11.4 文件光标移动函数fseek函数原型和头文件:

11.5 文件关闭函数fclose函数原型和头文件:

11.6 标准C库对文件打开写入读取关闭编程实现:

十二、标准C库写入结构体到文件

12.1 写一个整数到文件:

12.2 写一个结构体到文件:

12.3 写一个结构体数组到文件:

十三、文件其它函数讲解及文件收尾

13.1 文件写入字符函数fputc函数原型和头文件:

13.2 使用fputc函数写一个字符到文件:

13.3 使用fputc函数写多个字符到文件:

13.4 文件读取字符函数fgetc函数原型和头文件:

13.5 文件尾巴检测函数feof函数原型和头文件:

13.6 使用feof函数检测是否到文件尾部并使用fgetc函数读出文件内容:

一、文件编程概述

之前在windows中对文件的操作是:打开文档——>编辑文档——>保存文档——>关闭文档

我们的Linux文件编程主要是利用代码对文件进行操作:文件创建、打开、编辑等自动化执行等

在Linux我们要使用编程调用api函数的方式进行文档的编辑:

打开:open        读写:write/read        光标定位:lseek        关闭:close 

二、文件打开与创建

2.1 文件打开创建函数open原型和头文件:

/*
	Linux下:man 2 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 creat(const char *pathname, mode_t mode);

返回值     文件描述符
pathname (含路径,缺省为当前路径)
flags     权限 O_RDONLY:只读打开        O_WRONLY:只写打开        O_RDWR:可读可写打开
mode 	  权限模式
1.可读:        r         4
2.可写:        w         2
3.可执行        x         1
0600:6代表4+2(可读可写)

2.2 open函数打开一个文件:

  • 利用open函数打开file1文件,如果文件存在则返回3,否则返回-1

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

int main()
{
	int fd;

	fd = open("./file1",O_RDWR);
	
	printf("fd = %d\n",fd);
	return 0;
}

我们刚开始touch了一个file1文件,用open函数可以打开这个文件,返回3

我们rm删除了file1文件,用open函数打开这个文件就失败了,返回-1

2.3 open函数打开文件失败创建一个文件:

  • 使用open函数打开file1文件失败后,就创建一个file1文件

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

int main()
{
	int fd;

	fd = open("./file1",O_RDWR);					//使用open函数打开file1文件
	if(fd == -1){									//如果打开失败
		printf("file1 no failed\n");				//输出文件1号失败	
		fd = open("./file1",O_RDWR|O_CREAT,0600);	//文件不存在则创建它,需要同时说明第三个参数mode,权限为可读可写
		if(fd > 0){
			printf("create file1 success!\n");		//若文件描述符>0则代表创建文件成功!
		}
	}
		
	return 0;
}

最终我们可以看到创建file1文件成功!

//我们创建的file1文件权限为:可读可写
查看文件权限指令:ls -l
r 代表“可读”
w 代表“可写”
x 代表“可执行”
    
mode       权限模式
1.可读:        r         4
2.可写:        w         2
3.可执行        x         1
0600:6代表4+2(可读可写)

2.4 查看文件是否存在:

/*O_EXCL如果同时指定了O_CREAT,而文件已经存在,那么打开文件失败*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

int main()
{
	int fd;

	fd = open("./file1",O_RDWR|O_CREAT|O_EXCL,0600);
	if(fd == -1){				//如果O_EXCL和O_CREAT同时使用时,文件已经存在就返回-1代表文件存在
		printf("file cunZai\n");
	}
	return 0;
}

2.5 每次写内容都到文件的尾部:

当前我们file1文件中的内容是:

如果直接往里面添加内容会出现错误,会从头开始添加,我们不希望破坏之前的内容,我们可以在open函数的可读可写权限后面或上O_APPEND

/*O_APPEND 每次写时都加到文件的尾端*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main()
{
	int fd;
	char *buf = "chenlichen handsome";

	fd = open("./file1",O_RDWR|O_APPEND);	//添加O_APPEND后写入的内容就会从file1文件的尾部添加

	printf("open susceess:fd = %d\n",fd);

	//size_t write(int fd, const void *buf, size_t count);
	int n_write = write(fd,buf,strlen(buf));		 		//将buf中的内容写入到fd对应的文件中
    if(n_write != -1){										//如果函数返回值不是-1代表写入成功
		printf("success write %d byte to file1\n",n_write);	//输出写入到file1文件中多少个自己
	}
	
	close(fd);										//关闭刚写入的文件
	return 0;
}

2.6 O_TRUNC打开已有内容的文件并删除所有内容:

当前我们file1文件中的内容是:

O_TRUNC 属性去打开文件时,如果这个文件中本来是有内容的,而且为只读或只写成功打开,则将其长度截短为0

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

int main()
{
	int fd;
	char *buf = "test";

	fd = open("./file1",O_RDWR|O_TRUNC);	//O_TRUNC打开已有内容的文件并删除所有内容

	printf("open susceess:fd = %d\n",fd);

	//size_t write(int fd, const void *buf, size_t count);
	int n_write = write(fd,buf,strlen(buf));		 		//将buf中的内容写入到fd对应的文件中
    if(n_write != -1){										//如果函数返回值不是-1代表写入成功
		printf("success write %d byte to file1\n",n_write);	//输出写入到file1文件中多少个自己
	}
	
	close(fd);										//关闭刚写入的文件
	return 0;
}

我们可以看到使用O_TRUNC打开已有内容的文件,会将文件中的内容全部删除,我们又重新写入了test内容

2.7 文件创建creat函数原型和头文件:

/*
	Linux下:man creat可以查看对应手册
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int creat(const char *pathname, mode_t mode);

返回值		  	  文件描述符
pathname		  要创建的文件名(含路径、缺省为当前路径)	
mode_t mode       创建模式
   宏表示   数字    
1.S_IRUSR	4	可读
2.S_IWUSR	5	可写
3.S_IXUSR	1	可执行
4.S_IRWXU	7	可读、可写、可执行   

2.8 使用creat函数创建一个文件:

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

int main()
{
	int fd;
	
	fd = creat("/home/CLC/file1",S_IRWXU);	//使用creat函数在绝对路径下创建了file1文件,权限为可读、可写、可执行
	printf("creat file:fd = %d\n",fd);		//文件描述符
	return 0;
}

三、文件写入操作编程

3.1 文件写入函数write和文件关闭函数close原型和头文件:

/*
	Linux下:man 2 write可以查看对应手册
*/

#include <unistd.h>

ssize_t write(int fd, const void *buf, size_t count);

int fd 		     写入到刚打开的文件中
const void *buf  无符号类型的字符缓冲区
size_t count     写入的字节大小
ssize_t          若成功写入文件,函数返回值为写入字节个数,若失败,返回-1。
    
/*
	Linux下:man 2 close可以查看对应手册
*/
 
#include <unistd.h>
    
int close(int fd);

int fd           关闭刚写入的文件,一般在写入文件后执行文件的关闭

3.2 对文件写入内容:

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

int main()
{
	int fd;
	char *buf = "chenlichen handsome";

	fd = open("./file1",O_RDWR);					//使用open函数打开file1文件		
	if(fd == -1){									//如果打开失败
		printf("file1 no failed\n");				//输出文件1号失败	
		fd = open("./file1",O_RDWR|O_CREAT,0600);	//文件不存在则创建它,需要同时说明第三个参数mode,权限为可读可写
		if(fd > 0){
			printf("create file1 success!\n");		//若文件描述符>0则代表创建文件成功!
		}
	}
	printf("open susceess : fd = %d\n",fd);			//输出创建或者打开的文件的文件描述符
    
	//ssize_t write(int fd, const void *buf, size_t count);
	int n_write = write(fd,buf,strlen(buf));		 		//将buf中的内容写入到fd对应的文件中
    if(n_write != -1){										//如果函数返回值不是-1代表写入成功
		printf("success write %d byte to file1\n",n_write);	//输出写入到file1文件中多少个自己
	}
	
	close(fd);										//关闭刚写入的文件
	return 0;
}

通过open函数成功打开了file1文件,并将内容chenlichen handsom(19个字节)写入到文件中

 

 通过open函数打开file1文件失败后,创建了一个file1文件,创建的文件文件描述符是3,并将内容chenlichen handsome(19个字节)写入到文件中

四、文件读取操作编程

4.1 文件读取函数read函数原型和头文件:

/*
	Linux下:man 2 read可以查看对应手册
*/

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);	

fd				文件描述符
void *buf		待读入缓冲区
size_t count	读出字节个数
ssize_t			若成功读取文件,函数返回值为读出字节个数,若失败,返回-1 
    
read函数作用:从fd指向的文件读取count个字节的数据放到buf缓冲区里面

4.2 使用read函数读取文件中的内容:

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

int main()
{
	int fd;
	char *buf = "chenlichen handsome";

	fd = open("./file1",O_RDWR);							//使用open函数打开file1文件		
	if(fd == -1){											//如果打开失败
		printf("file1 no failed\n");						//输出文件1号失败	
		fd = open("./file1",O_RDWR|O_CREAT,0600);	//文件不存在则创建它,需要同时说明第三个参数mode,权限为可读可写
		if(fd > 0){
			printf("create file1 success!\n");				//若文件描述符>0则代表创建文件成功!
		}
	}
	printf("open susceess : fd = %d\n",fd);					//输出创建或者打开的文件的文件描述符
    
	//ssize_t write(int fd, const void *buf, size_t count);
	int n_write = write(fd,buf,strlen(buf));		 		//将buf中的内容写入到fd对应的文件中
    if(n_write != -1){										//如果函数返回值不是-1代表写入成功
		printf("success write %d byte to file1\n",n_write);	//输出写入到file1文件中多少个自己
	}

	char *readBuf;

	readBuf = (char *)malloc(sizeof(char) * n_write + 1);	//写入了多少个字节就开辟多少个字节的空间
	//ssize_t read(int fd, void *buf, size_t count);
	int n_read = read(fd,readBuf,n_write);			//从fd指向的文件读取n_write个字节的数据放到readBuf缓冲区里面

	printf("read %d,context:%s\n",n_read,readBuf);			//读取了多少字节,读取到文件中的内容
	close(fd);												//关闭文件
	return 0;
}

我们可以看到我们向file1文件中写入了chenlichen handsome,但是使用read函数读取文件中的内容到readBuf中,但是读取到的字节为0,并且也没有读取到内容,这是因为我们往file1文件中写入了chenlichen handsome后,文件中光标的位置已经到了尾巴,如果想要读取成功需要将光标移动到头,后面再使用此方法

这次我们这样:把写入内容到file1文件中后把文件关闭,读取的时候再重新的打开

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

int main()
{
	int fd;
	char *buf = "chenlichen handsome";

	fd = open("./file1",O_RDWR);							//使用open函数打开file1文件		
	if(fd == -1){											//如果打开失败
		printf("file1 no failed\n");						//输出文件1号失败	
		fd = open("./file1",O_RDWR|O_CREAT,0600);	//文件不存在则创建它,需要同时说明第三个参数mode,权限为可读可写
		if(fd > 0){
			printf("create file1 success!\n");				//若文件描述符>0则代表创建文件成功!
		}
	}
	printf("open susceess : fd = %d\n",fd);					//输出创建或者打开的文件的文件描述符
    
	//ssize_t write(int fd, const void *buf, size_t count);
	int n_write = write(fd,buf,strlen(buf));		 		//将buf中的内容写入到fd对应的文件中
    if(n_write != -1){										//如果函数返回值不是-1代表写入成功
		printf("success write %d byte to file1\n",n_write);	//输出写入到file1文件中多少个自己
	}

	close(fd);												//往file1文件中写入内容成功后“关闭文件”
	fd = open("./file1",O_RDWR);							//读取前重新打开,目的就是让光标回到头

	char *readBuf;

	readBuf = (char *)malloc(sizeof(char) * n_write + 1);	//写入了多少个字节就开辟多少个字节的空间
	//ssize_t read(int fd, void *buf, size_t count);
	int n_read = read(fd,readBuf,n_write);			//从fd指向的文件读取n_write个字节的数据放到readBuf缓冲区里面

	printf("read %d,context:%s\n",n_read,readBuf);			//读取了多少字节,读取到文件中的内容
	close(fd);	
	return 0;
}

使用这种方式让光标回到头还是比较“蠢”的,关于光标回到头还是有更好的方式的,下次再解决!

五、文件光标移动操作

5.1 文件光标移动函数lseek函数原型和头文件:

/*
	Linux下:man 2 lseek可以查看对应手册
*/

#include <sys/types.h>
#include <unistd.h>

off_t lseek(int fd, off_t offset, int whence);

off_t			若成功移动光标,函数返回值为光标移动个数,若失败,返回-1
fd				文件描述符
off_t offset	针对whence光标偏移个数 
int whence		光标的绝对位置        
1.SEEK_SET  文件头	      The offset is set to offset bytes.	
2.SEEK_CUR  光标当前位置	The offset is set to its current location plus offset bytes.	
3.SEEK_END  文件内容末尾	The offset is set to the size of the file plus offset bytes.
				
lseek函数作用:将文件读写指针相对whence移动offset个字节

5.2 使用lseek函数对文件进行操作:

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

int main()
{
	int fd;
	char *buf = "chenlichen handsome";

	fd = open("./file1",O_RDWR);							//使用open函数打开file1文件		
	if(fd == -1){											//如果打开失败
		printf("file1 no failed\n");						//输出文件1号失败	
		fd = open("./file1",O_RDWR|O_CREAT,0600);	//文件不存在则创建它,需要同时说明第三个参数mode,权限为可读可写
		if(fd > 0){
			printf("create file1 success!\n");				//若文件描述符>0则代表创建文件成功!
		}
	}
	printf("open susceess : fd = %d\n",fd);					//输出创建或者打开的文件的文件描述符
    
	/*ssize_t write(int fd, const void *buf, size_t count); write函数原型*/
	int n_write = write(fd,buf,strlen(buf));		 		//将buf中的内容写入到fd对应的文件中
    if(n_write != -1){										//如果函数返回值不是-1代表写入成功
		printf("success write %d byte to file1\n",n_write);	//输出写入到file1文件中多少个自己
	}

	char *readBuf;
	readBuf = (char *)malloc(sizeof(char) * n_write + 1);	//写入了多少个字节就开辟多少个字节的空间

	/*off_t lseek(int fd, off_t offset, int whence); lseek函数原型*/
	lseek(fd,0, SEEK_SET);		//将光标移动到头
//	lseek(fd,-19, SEEK_END);	//将光标从尾巴移动到头
//	lseek(fd,-19, SEEK_CUR);	//将光标从当前位置移动到头
    
	/*ssize_t read(int fd, void *buf, size_t count); read函数原型*/
	int n_read = read(fd,readBuf,n_write);			//从fd指向的文件读取n_write个字节的数据放到readBuf缓冲区里面

	printf("read %d,context:%s\n",n_read,readBuf);			//读取了多少字节,读取到文件中的内容
	close(fd);	
	return 0;
}

针对于我们读取文件时遇到的问题,我们通过lseek函数将光标移动到头,成功读取到file1文件中的内容

5.3 使用lseek函数可以的巧妙的计算文件大小:

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

int main()
{
	int fd;

	fd = open("./file1",O_RDWR);				//使用open函数打开file1文件	

	int filesize = lseek(fd, 0, SEEK_END);		//使用lseek函数计算file1文件的大小
	printf("file's size is :%d\n",filesize);	//打印输出

	close(fd);									//关闭文件
	return 0;
}

我们使用ls -l指令可以查看到file1文件的大小是19个字节,我们调用lseek函数可以巧妙的查看文件的大小

六、文件操作原理简述

文件编程的一般步骤:

打开/创建文件 − > ->−> 读取文件/写入文件 − > ->−> 关闭文件

 

Linux文件管理简述:

 

七、文件编程练手(一)实现copy指令(面试)

7.1 copy指令在Linux下的应用:  

copy 指令在Linux系统是一个常用的指令,就是这样用:

cp demo4.c demo13.c

其中 copy是指令,demo4.c是源文件,demo13.c是目标文件,下面我们就来编程

7.2 main函数的参数:

/*main函数参数功能*/
int main(int argc,char **argv)
    
int argc		argc 表示运行C文件参数的个数
char **argv 	argv是字符数组指针,每个指针都是一个数组,在这里表示每个参数的内容

下面我们验证一下:

#include <stdio.h>

int main(int argc, char **argv)
{
	printf("total params: %d\n",argc);		//C文件参数个数有三个
	printf("No.1 params: %s\n",argv[0]);	//第一个
	printf("No.2 params: %s\n",argv[1]);	//第二个
	printf("No.3 params: %s\n",argv[2]);	//第三个
	return 0;
}

我们搞清楚main函数的参数是:./a.out src des
这样我们就可以把文件名传进去进行响应的拷贝操作如:cp demo13.c new.c

7.3 文件编程实现copy指令:

用文件编程实现copy指令的编程思路:

  1. 打开源文件src.c

  2. 读源文件src.c到buf

  3. 打开/创建目标文件des.c

  4. 将buf写入到目标文件des.c

  5. 关闭两个文件

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

int main(int argc, char **argv)
{
	int fdSrc;
	int fdDes;

	char *readBuf = NULL;
	
	if(argc != 3){										//判断C文件参数是不是有三个,如果不是程序退出
		printf("param error\n");
		exit(-1);
	}

	fdSrc = open(argv[1],O_RDWR);						//打开源文件demo13.c
	
	int size = lseek(fdSrc,0, SEEK_END);				//计算源文件有多少个字节
	lseek(fdSrc, 0, SEEK_SET);							//让源文件光标回到头
	
	readBuf = (char *)malloc(sizeof(char) * size + 8);	//动态开辟readBuf的内存空间

	int n_read = read(fdSrc,readBuf,size);				//把源文件的size个字节的内容读取到readBuf里面

	fdDes = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600);	//打开目标文件new.c,如果打开失败就创建目标文件new.c
														//如果存在目标文件,就把文件中的内容全部干掉,否则会出错
	int n_write = write(fdDes,readBuf,strlen(readBuf));	//将readBuf里面的内容写入到目标文件new.c中

	close(fdSrc);										//关闭源文件
	close(fdDes);										//关闭目标文件
	return 0;
}

我们可以看到打开我们cp的new.c文件,和源文件demo13.c内容是一模一样的,这样就使用文件编程实现了copy指令

八、文件编程练手(二)修改程序的配置文件(工作常用)

在工作中我们经常会遇到修改配置文件相关的问题,比如以下配置文件:

我们要把LENG修改成5,我们该怎么办呢?

8.1 使用文件编程修改配置文件的指定内容:

编程思路:

  1. 打开配置文件

  2. 读出配置文件内容

  3. 找到LENG字符串的起始位置

  4. 偏移LENG的长度,偏移到数据位置

  5. 更改数据位置的值

  6. 把读出的内容重新写入配置文件

  7. 关闭文件

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

int main(int argc, char **argv)
{
	int fdSrc;

	char *readBuf = NULL;
	
	if(argc != 2){											//判断C文件参数是不是有两个,如果不是程序退出
		printf("param error\n");
		exit(-1);
	}

	fdSrc = open(argv[1],O_RDWR);							//打开配置文件
	
	int size = lseek(fdSrc,0, SEEK_END);					//计算配置文件有多少个字节
	lseek(fdSrc, 0, SEEK_SET);								//让配置文件光标回到头
	
	readBuf = (char *)malloc(sizeof(char) * size + 8);		//动态开辟readBuf的内存空间

	int n_read = read(fdSrc,readBuf,size);					//把配置文件的size个字节的内容读取到readBuf里面

	//char *strstr(const char *haystack, const char *needle);
	char *p = strstr(readBuf,"LENG=");				//字符串查找函数,返回值为要查找的字符串的第一个字符的指														      针,第一个参数为待查找的原始字符串,第二个参数为要查找的内容
	p = p + strlen("LENG=");									//偏移LENG的长度,偏移到数据位置
	*p = '5';													//更改数据位置的值

	lseek(fdSrc, 0, SEEK_SET);									//让配置文件光标回到头

	int n_write = write(fdSrc,readBuf,strlen(readBuf));			//把读出的内容重新写入配置文件

	close(fdSrc);												//关闭配置文件
	return 0;
}

8.2 字符串比较函数strstr原型和头文件:

/*
	Linux下 man strstr可以查看对应手册
*/
#include <string.h>

char *strstr(const char *haystack, const char *needle);		//字符串查找函数

char *					返回值为要查找的字符串的第一个字符的指针
const char *haystack	待查找的原始字符串
const char *needle		为要查找的内容  

九、写一个整数、结构体和结构体数组到文件

前面我们都是写字符串到文件中,那可不可以写入整数或者结构体呢?

ssize_t write(int fd, const void *buf, size_t count);
ssize_t read(int fd, void *buf, size_t count);	

这两个是写and读的函数原型,我们可以发现第二个参数都是:void *buf
这样我们即可以写入字符串,又可以将整数或者结构体的地址传递过去,进行读和写

9.1 写一个整数到文件:

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

int main()
{
	int fd;
	int data = 100;
	int data2;

	fd = open("./file1",O_RDWR);							//打开file1文件

	//size_t write(int fd, const void *buf, size_t count);
	int n_write = write(fd,&data,sizeof(int));				//写整数100到文件

	lseek(fd, 0, SEEK_SET);									//写完之后,光标回到文件头
	//ssize_t read(int fd, void *buf, size_t count);
	int n_read = read(fd,&data2,sizeof(data2));				//把file1文件中的内容读4个字节到data2中

	printf("read %d\n",data2);								//输出读取的结果
	close(fd);
	return 0;
}

成功向file1文件中写入了一个整数,并且把文件中的整数读取到了data2中,最终输出结果

打开我们发现是乱码的,是因为整数在文件中的体现方式并不是我们肉眼看到的那样,只要程序可以成功写入/读取即可

9.2 写一个结构体到文件:

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

struct Test
{
	int idata;
	char cdata;
};

int main()
{
	int fd;
	struct Test t1 = {100,'#'};								//定义一个结构体变量并赋初值
	struct Test t2;

	fd = open("./file1",O_RDWR);							//打开file1文件

	//size_t write(int fd, const void *buf, size_t count);
	int n_write = write(fd,&t1,sizeof(struct Test));		//写一个结构体到文件中

	lseek(fd, 0, SEEK_SET);									//写完之后,光标回到文件头
	//ssize_t read(int fd, void *buf, size_t count);
	int n_read = read(fd,&t2,sizeof(struct Test));			//读文件中的结构体到t2中

	printf("read t2 = %d,%c\n",t2.idata,t2.cdata);			//输出读取的结果
	close(fd);												//关闭文件
	return 0;
}

成功向file1文件中写入了一个结构体,并且把文件中的结构体读取到了t2中,最终输出结果

9.3 写一个结构体数组到文件:

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

struct Test
{
	int idata;
	char cdata;
};

int main()
{
	int fd;
	int i;
	struct Test arr1[2] = {									//定义一个arr1结构体数组并初始化

		{100,'#'},
		{200,'$'}
	};
	struct Test arr2[2];									//定义一个arr2结构体数组并初始化
	
	int arr1Size = sizeof(arr1) / sizeof(arr1[0]);			//计算arr1结构体数组的元素个数
	int arr2Size = sizeof(arr2) / sizeof(arr2[0]);			//计算arr2结构体数组的元素个数
		
	fd = open("./file1",O_RDWR);							//打开file1文件

	//size_t write(int fd, const void *buf, size_t count);
	int n_write = write(fd,&arr1,sizeof(struct Test) * arr1Size);	//把arr1结构体数组写到文件中

	lseek(fd, 0, SEEK_SET);											//写完之后,光标回到文件头
	//ssize_t read(int fd, void *buf, size_t count);
	int n_read = read(fd,&arr2,sizeof(struct Test) * arr2Size);		//把写入文件中的结构体数组读取到arr2中

	for(i=0; i<2; i++){	
		printf("read arr2 = %d,%c\n",arr2[i].idata,arr2[i].cdata);	//输出读取到的值
	}
	close(fd);														//关闭文件
	return 0;
}

成功向file1文件中写入了一个结构体数组,并且把文件中的结构体数组读取到了arr2中,最终输出结果

十、标准C库对文件操作引入

fopen与open的区别

1、来源不同 open是unix系统调用函数(包括Linux),返回的是文件描述符,它是文件描述符表里的索引。 fopen是ANSIC标准中的C语言库函数,在不同的系统中应该调不同的内核api,返回的是一个指向文件结构的指针。

2、移植性 从来源看,fopen是C标准函数,因此拥有良好的移植性,而open是unix系统调用,移植性有限,如windows下相似的功能使用api函数CreatFile。

3、使用范围 open返回文件描述符,而文件描述符是unnix系统下的重要概念,unix下的一切设备都是文件的形式操作,如网络套接字、硬件设备等、当然包括操作普通正规文件(Regular File) Fopen是从来操纵普通正规文件(Regular File)的

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

5、 缓冲区 open没缓冲区(多次在用户态和内核态切换,执行速度慢,效率低),fopen有缓冲区(在缓冲区读写后一次性写入文件,执行速度快,效率高)

更多详细介绍观看此路径https://www.cnblogs.com/NickyYe/p/5497659.html念这些啰里啰唆的概念不是我的风格!!!

主打的就是一个拽!!!

十一、标准C库打开创建文件读写关闭文件和光标移动

11.1 打开创建文件函数fopen函数原型和头文件:

/*
	Linux下 man fopen查看手册
*/
#include <stdio.h>

FILE *fopen(const char *path, const char *mode);

FILE *				返回值并不是文件描述符,若失败返回NULL,若操作成功返回FILE指针
const char *path	文件路径
const char *mode	打开方式
    
mode 打开模式:
r	只读方式打开一个文本文件
rb	只读方式打开一个二进制文件
w	只写方式打开一个文本文件
wb	只写方式打开一个二进制文件
a	追加方式打开一个文本文件
ab	追加方式打开一个二进制文件
r+	可读可写方式打开一个文本文件
rb+	可读可写方式打开一个二进制文件
w+	可读可写方式创建一个文本文件
wb+	可读可写方式生成一个二进制文件
a+	可读可写追加方式打开一个文本文件
ab+	可读可写方式追加一个二进制文件

11.2 文件写入函数fwrite函数原型和头文件:

/*
	Linux下 man fwrite查看手册
*/
#include <stdio.h>

size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);

size_t				返回值若成功写入文件,函数返回值为写入次数(函数第三个参数),若失败,返回非写入字节个数或0
const void *ptr		是写的数据存放的缓冲区 
size_t size			每次写的字节数
size_t nmemb    	写入数据的次数
FILE *stream		表示要写入哪个文件(已打开文件的指针,一般就是fopen的返回值)

11.3 文件读取函数fread函数原型和头文件:

/*
	Linux下 man fread查看手册
*/
#include <stdio.h>

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
	
size_t			若成功读出文件,函数返回值为读取总共字节个数(函数第三个参数),若失败,返回非写入字节个数或0
void *ptr		读的数据存放的缓冲区
size_t size	  	每次读的字节数
size_t nmemb    读取数据的次数
FILE *stream	表示要读取哪个文件(已打开文件的指针,一般就是fopen的返回值)   

11.4 文件光标移动函数fseek函数原型和头文件:

/*
	Linux下 man fseek查看手册
*/
#include <stdio.h>

int fseek(FILE *stream, long offset, int whence);

int				函数返回值,若成功移动光标,函数返回值为0,若失败,返回-1
FILE *stream	要移动光标的文件
long offset		针对whence光标偏移个数
int whence		光标的绝对位置
    
1.SEEK_SET  文件头	      The offset is set to offset bytes.	
2.SEEK_CUR  光标当前位置	The offset is set to its current location plus offset bytes.	
3.SEEK_END  文件内容末尾	The offset is set to the size of the file plus offset bytes.

11.5 文件关闭函数fclose函数原型和头文件:

/*
	Linux下 man fclose查看手册
*/
#include <stdio.h>

int fclose(FILE *fp);

int			函数返回值,成功关闭文件则返回0,非则返回EOF
FILE *fp	表示要关闭哪个文件(已打开文件的指针,一般就是fopen的返回值)

11.6 标准C库对文件打开写入读取关闭编程实现:

#include <stdio.h>
#include <string.h>

int main()
{
	FILE *fp;
	char *str = "chenlichen handsome";
	char readBuf[128] = {0};

	//FILE *fopen(const char *path, const char *mode);
	fp = fopen("./chen.txt","w+");						//可读可写方式创建一个文本文档并打开,文件名chen.txt

	//size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
	fwrite(str,sizeof(char),strlen(str),fp);			//把str中的内容写入到文件中,一次写1个字节,写strlen(str)次
	//fwrite(str,sizeof(char)*strlen(str),1,fp);		//把str中的内容写入到文件中,一次把所有内容写入到文件中
	
	//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);		//把文件中的内容读取到readBuf中,一次读一个字节,读strlen(str)次
	//fread(readBuf,sizeof(char),strlen(str),fp);		//把文件中的内容读取到readBuf中,一次把所有内容全部读出
    
	printf("read data: %s\n",readBuf);				//输出从文件中读取到readBuf的内容

	fclose(fp);										//关闭文件
	return 0;
}

十二、标准C库写入结构体到文件

12.1 写一个整数到文件:

#include <stdio.h>

int main()
{
	FILE *fp;
	int data = 100;
	int data2;

	fp = fopen("./file1","w+");							//打开file1文件,没有的话就创建

	//size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
	fwrite(&data,sizeof(int),1,fp);						//写一个整数到文件中

	fseek(fp, 0, SEEK_SET);								//写完之后,光标回到文件头

	//size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
	fread(&data2,sizeof(int),1,fp);						//把文件中的整数读取到data2中
	
	printf("read %d\n",data2);							//输出读取到的内容
	fclose(fp);											//关闭文件
	return 0;
}

12.2 写一个结构体到文件:

#include <stdio.h>

struct Test
{
	int idata;
	char cdata;
};

int main()
{
	FILE *fp;
	struct Test t1 = {100,'#'};						//定义一个结构体变量并赋值
	struct Test t2;

	fp = fopen("./file1","w+");						//打开file1,如果没有就创建

	//size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
	fwrite(&t1,sizeof(struct Test),1,fp);			//将结构体写到文件中
	
	fseek(fp, 0, SEEK_SET);							//写完之后,光标回到头

	//size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
	fread(&t2,sizeof(struct Test),1,fp);			//把文件中的结构体读取到t2中

	printf("read t2 = %d,%c\n",t2.idata,t2.cdata);	//输出读取的结果
	fclose(fp);										//关闭文件
	return 0;
}

12.3 写一个结构体数组到文件:

#include <stdio.h>

struct Test
{
	int idata;
	char cdata;
};

int main()
{
	FILE *fp;
	int i;
	struct Test arr1[2] = {											//定义一个结构体数组并初始化

		{100,'#'},
		{200,'$'}
	};
	struct Test arr2[2];
	
	int arr1Size = sizeof(arr1) / sizeof(arr1[0]);					//计算arr1的元素个数
	int arr2Size = sizeof(arr2) / sizeof(arr2[0]);					//计算arr2的元素个数
		
	fp = fopen("./file1","w+");										//打开file1文件,没有就创建

	//size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
	fwrite(&arr1,sizeof(struct Test)*arr1Size,1,fp);				//把arr1结构体数组写入到文件中
	
	fseek(fp, 0, SEEK_SET);											//写完之后,光标回到头

	//size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
	fread(&arr2,sizeof(struct Test)*arr2Size,1,fp);					//把文件中的结构体数组读取到arr2中
	
	for(i=0; i<2; i++){	
		printf("read arr2 = %d,%c\n",arr2[i].idata,arr2[i].cdata);	//输出读取到的结构体数组
	}
	fclose(fp);														//关闭文件
	return 0;
}

十三、文件其它函数讲解及文件收尾

13.1 文件写入字符函数fputc函数原型和头文件:

/*
	Linux下 man fputc查看手册
*/
#include <stdio.h>

int fputc(int c, FILE *stream);

int 			函数返回值,若成功写入文件,函数返回值为写入文件的字符的ASCII码值,若出错,返回EOF(-1)
int c			要写入的字符   
FILE *stream	表示要写入哪个文件(已打开文件的指针,一般就是fopen的返回值)

13.2 使用fputc函数写一个字符到文件:

#include <stdio.h>

int main()
{
	FILE *fp;
	char cdata = '#';					//要写入的内容
	
	fp = fopen("test.txt","w+");		//打开file1文件,如果没有就创建
	
	fputc(cdata,fp);					//写字符到file1文件
	fclose(fp);							//关闭文件
	return 0;
}

13.3 使用fputc函数写多个字符到文件:

#include <stdio.h>
#include <string.h>

int main()
{
	FILE *fp;
	int i;
	char *str = "chenlichen handsome";		//定义一个字符串
	char readBuf[128] = {0};	

	int len = strlen(str);					//计算字符串的长度
	fp = fopen("test.txt","w+");			//打开file1文件,如果没有就创建
	
	for(i=0; i<len; i++){					//使用for循环一个一个的将字符串中的字符写入到文件中
		fputc(*str,fp);
		str++;								//指针偏移
	}
	//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)*len,1,fp);	//将文件中的内容读取到readBuf里面
	
	printf("read %s\n",readBuf);			//输出读取到的内容
	fclose(fp);								//关闭文件
	return 0;
}

13.4 文件读取字符函数fgetc函数原型和头文件:

/*
	Linux下 man fgetc查看手册
*/
#include <stdio.h>

int fgetc(FILE *stream);

int				函数返回值,若成功读出文件,函数返回值为读出文件的内容,若出错或读到末尾,返回EOF(-1)
FILE *stream	表示要读取哪个文件(已打开文件的指针,一般就是fopen的返回值)

13.5 文件尾巴检测函数feof函数原型和头文件:

/*
	Linux下 man feof查看手册
*/
#include <stdio.h>

int feof(FILE *stream);

int 			函数返回值,若到文件末尾,函数返回值为非0,若不到末尾,返回0
FILE *stream	表示要判断的文件

13.6 使用feof函数检测是否到文件尾部并使用fgetc函数读出文件内容:

#include <stdio.h>

int main()
{
	FILE *fp;
	char c;

	fp = fopen("./test.txt","r");		//只读方式打开当前路径的test.txt文件

	while(!feof(fp)){					//判断是否到文件尾部
		c = fgetc(fp);					//没有到文件尾部就一个字符一个字符的读出文件的内容
		printf("%c",c);					//读一次输出一次
	}
	fclose(fp);							//关闭文件
	return 0;
}

  • Linux系统一切皆文件文件系统(文件夹 /文件 ) 硬件设备 管道 数据库 Socket等,文件还是非常重要的,文件的操作就先到这里!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值