【c语言】文件操作

1.使用文件的原因

我们都知道,当我们结束一个程序时,程序里的数据会随之在内存上消失。
使用文件的好处在于我们可以把数据保存到文件中,或者需要从文件加载配置信息。

下面是内存和硬盘的关系,可以帮助我们理解文件的作用:
在这里插入图片描述
下面就简单介绍文件的使用。

2.预备知识

a._iobuf结构体

当我们打开一个文件的时候,就会将创建一个结构体,将一些信息保存到这里面。
这个结构体了解一下就好,我们不需要仔细研究。

struct _iobuf 
{
    char *_ptr;  ------当前缓冲区内容指针
    int   _cnt;  ------缓冲区还有多少字符
    char *_base; ------缓冲区的起始地址
    int   _flag;  ------文件流的状态,是否错误或结束
    int   _file; -----文件描述符
    int   _charbuf;  -----双字节缓冲,缓冲2个字节
    int   _bufsiz;  -----缓冲区大小
    char *_tmpfname;  -----临时文件名
};


typedef struct _iobuf FILE;

b.文件指针

文件指针比较简单,FILE是文件结构体类型,声明文件指针如下:

FILE* p;			声明一个文件指针

后面会经常用到。

c.文件的打开方式

操作方式解释如果文件不存在
“r”只读,为了读取文件,打开一个已存在的文本文件出错
“w”只写,为了写入文件,打开一个文本文件自动创建一个文件
“a”追加,在文本文件末尾追加数据自动创建一个文件
rb只读,为了读取文件,打开一个已存在的二进制文件出错
rw只写,为了写入文件,打开一个二进制文件自动创建一个文件
ab追加,在二进制文件末尾追加数据自动创建一个文件
r+读写,为了读取和写入文件,打开一个已存在的文本文件出错
w+读写,为了读取和写入文件,打开一个文本文件自动创建一个文件
a+读写,在文本文件末尾进行读取和写入自动创建一个文件
rb+读写,为了读取和写入文件,打开一个已存在的二进制文件出错
wb+读写,为了读取和写入文件,打开一个二进制文件自动创建一个文件
ab+读写,在二进制文件末尾进行读取和写入自动创建一个文件

d.文件的打开和关闭

打开文件函数:fopen

FILE * fopen ( const char * filename, const char * mode );
形参:	const char* filename	文件名
		const char* mode		打开文件的方式

返回值:	文件(FILE)指针

打开文件示例:

#include<stdio.h>
#include<stdlib.h>
int main()
{
	//以只读的方式打开test.txt文件
	FILE* p = fopen("test.txt", "r");
	return 0;
}

关闭文件函数:fclose

int fclose ( FILE * stream );
形参:	FILE* stream			文件指针
返回值:	如果关闭文件成功,返回0
		如果关闭文件失败,返回EOF

关闭文件示例:

#include<stdio.h>
#include<stdlib.h>
int main()
{
	//以只读的方式打开test.txt文件
	FILE* p = fopen("test.txt", "r");
	//关闭文件,以免浪费资源
	fclose(p);
	return 0;
}

3.文件的顺序读写

a.字符输入输出函数

I.fgetc

int fgetc ( FILE * stream );
形参:	FILE* stream	指向文件的指针

返回值:	如果读取成功,返回读取到字符的ASCII码值
		如果到文件末尾或者读取失败,都会返回EOF

例子:

先创建一个test.txt文本文件,再从文件里读取字符

在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>

int main()
{
	//打开文件
	FILE* p = fopen("test.txt", "r");
	
	//检查是否打开成功
	if (p == NULL)
	{
		perror("opening file fail!\n");
	}
	
	//读入一个字符
	int c = fgetc(p);
	//输出
	printf("%c\n", c);
	
	//关闭文件
	fclose(p);
	p = NULL;
	return 0;
}

输出:

a

II.fputc

int fputc ( int character, FILE * stream );
形参:	int character		写入的字符
		FILE* stream		文件指针
		
返回值:	如果写入成功,返回写入的字符的ASCII码值
		如果写入失败或,返回EOF
		

示例:

#include<stdio.h>
#include<stdlib.h>
int main()
{
	//以只写的方式打开文件
	FILE* p = fopen("test.txt", "w");
	if (p == NULL)
	{
		perror("fail to open file\n");
	}
	//写入字符a
	fputc('a', p);
	fputc('a', p);
	fputc('a', p);
	fputc('a', p);
	fputc('a', p);
	fclose(p);
	p = NULL;
}

写入前:
在这里插入图片描述
写入后:
在这里插入图片描述

b.字符串输入输出函数

I.fgets

char * fgets ( char * str, int n, FILE * stream );
形参:	char* str		指向字符数组的指针,读取的数组会保存到字符数组里
		int n			读取不超过n的字符,最多读取n-1个
		FILE* stream	文件指针		

返回值:	如果读取成功,返回指向读取的字符串的指针
		如果没有读取到字符串或者读取失败的时候,都会返回NULL指针

示例:
在这里插入图片描述
读取这个文件里的前两个字符:

#include<stdio.h>
#include<stdlib.h>

int main()
{
	char str[10];
	FILE* p = fopen("test.txt", "r");
	if (p == NULL)
	{
		perror("file to open file\n");
	}
	//读取前两个字符,并将它们存到str字符数组里
	fgets(str, 3, p);
	printf(str);
	fclose(p);
	p = NULL;
	return 0;
}

输出:

aa

II.fputs

int fputs ( const char * str, FILE * stream );
形参:	const char* str		指向要写入文件的字符串的指针
		FILE* stream		文件指针		

返回值:	写入文件成功,返回非负数
		失败返回EOF

示例:

#include<stdio.h>
#include<stdlib.h>

int main()
{
	char str[20] = "China";
	//以只写的方式打开文件
	FILE* p = fopen("test.txt", "w");
	if (p == NULL)
	{
		perror("file to open file\n");
	}
	//将字符串"China"写入到文件中
	fputs(str, p);
	fclose(p);
	p = NULL;
	return 0;
}

写入前:
在这里插入图片描述

写入后:
在这里插入图片描述

c.格式化输入输出函数

I.fscanf

int fscanf ( FILE * stream, const char * format, ... );
形参:	FILE * stream			文件指针
		const char * format		输入格式
		...						可变形参,指向保存数据空间的指针

返回值:	读取成功,则返回读取到的项(格式中指定的项)的个数
		读取失败或者到文件末尾,则返回EOF

读取文件中的字符串:
在这里插入图片描述

示例:

#include<stdio.h>
#include<stdlib.h>

int main()
{
	char buffer[20];
	//打开文件
	FILE* p = fopen("test.txt", "r");
	if (p == NULL)
	{
		perror("open file fail\n");
	}
	//从文件中读取字符串到buffer中
	fscanf(p, "%s", buffer);
	//打印
	printf(buffer);
	fclose(p);
	p = NULL;
	return 0;
}

输出:

China

I.fprintf

int fprintf ( FILE * stream, const char * format, ... );
形参:	FILE * stream			文件指针
		const char * format		输出格式
		...						可变形参,各项数据

返回值:	写入成功,返回写入字符的个数
		写入失败,则返回EOF

示例:

#include<stdio.h>
#include<stdlib.h>

int main()
{
	//以只写的方式打开文件
	FILE* p = fopen("test.txt", "w");
	if (p == NULL)
	{
		perror("open file fail\n");
	}

	//从把数据写入到文件中
	fprintf(p, "%s", "今天吃火锅");

	fclose(p);
	p = NULL;
	return 0;
}

写入前:
在这里插入图片描述


写入后:
在这里插入图片描述


d.二进制输入输出函数

II.fwrite

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
形参:	void* ptr				指向一块内存空间
		size_t size				元素的大小
		size_t count			写入的元素个数
		FILE* stream			文件指针
		
返回值:	返回写入的元素个数
		如果元素的大小为0,或者元素的个数为0,返回0

示例:

#include<stdio.h>
#include<stdlib.h>

int main()
{
	int arr[10];
	for (int i = 0; i < 10; i++)
	{
		arr[i] = i + 1;
	}
	//以二进制只写的方式打开文件
	FILE* p = fopen("test.txt", "wb");
	if (p == NULL)
	{
		perror("open file fail\n");
	}

	//写入文件中
	int ret = fwrite(arr, sizeof(int), 10, p);
	printf("%d\n", ret);

	fclose(p);
	p = NULL;
	return 0;
}

输出:

10

文件的变化:
在这里插入图片描述
乱码了,这是正常的,因为是以二进制的方式写入文件中


I.fread

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
形参:	void* ptr				指向一块内存空间
		size_t size				元素的大小
		size_t count			写入的元素个数
		FILE* stream			文件指针
		
返回值:	返回读取到的元素个数
		如果元素的大小为0,或者元素的个数为0,返回0

示例:
介绍fwrite函数时已经把1-10写入文件了,这里使用fread把数据读出来,并打印

#include<stdio.h>
#include<stdlib.h>

int main()
{
	int arr[10];
	//以二进制只读的方式打开文件
	FILE* p = fopen("test.txt", "rb");
	if (p == NULL)
	{
		perror("open file fail\n");
	}

	//读文件
	int ret = fread(arr, sizeof(int), 10, p);
	
	//打印
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}

	fclose(p);
	p = NULL;
	return 0;
}

输出:

1 2 3 4 5 6 7 8 9 10

4.文件的随机读写

前面介绍的几个函数都是顺序读写的,
要是我们想要做到从指定位置开始读或者写,就要用到下面几个函数。

(1).fseek

如果要指定写入或者读取的位置,就要设置文件指针的位置
这时候就要用到fseek函数,帮我们设置文件指针到指定位置

int fseek ( FILE * stream, long int offset, int origin );
形参:	FILE* stream			文件指针
		long int offset			偏移量
		int origin				开始的位置

origin的几个参数:

常量位置
SEEK_SET文件的开始位置
SEEK_CUR文件指针当前的位置
SEEK_END文件的结束的位置
返回值:	设置成功,返回0
		设置失败,返回非0

注意:
指针的步长是一个字节


设置文件指针位置示例:

数据如下,我准备跳过两个字节,让文件指针指向C,然后读取
在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>

int main()
{
	char buffer;
	//打开文件
	FILE* p = fopen("test.txt", "r");
	if (p == NULL)
	{
		printf("打开文件失败\n");
	}
	
	// 设置文件指针的位置
	fseek(p, 2, SEEK_SET);
	
	//读数据
	fscanf(p, "%c", &buffer);
	printf("%c", buffer);

	//关闭文件
	fclose(p);
	p = NULL;
	return 0;
}

输出:

C

(2).ftell

当你一顿操作,然后不知道文件指针指向哪里的时候,
可以使用ftell函数告诉你指针的位置。

long int ftell ( FILE * stream );
形参:	FILE* stream
		
返回值:	相对文件起始位置的偏移量。

获取文件指针位置示例:

#include<stdio.h>
#include<stdlib.h>

int main()
{
	int ret = 0;
	//打开文件
	FILE* p = fopen("test.txt", "r");
	if (p == NULL)
	{
		printf("打开文件失败\n");
	}

	//获取文件指针位置, 此时获取的就是起始位置
	ret = ftell(p);
	printf("%d\n", ret);

	//设置完文件指针,此时获取的就是相对起始位置的偏移量
	fseek(p, 3, SEEK_SET);
	ret = ftell(p);
	printf("%d\n", ret);


	//关闭文件
	fclose(p);
	p = NULL;
	return 0;
}
0
3

(3).rewind

这个函数可以让文件指针快速回到起始位置,使用起来也很简单

void rewind ( FILE * stream );
形参:	FILE* stream	文件指针
		
返回值:	没有返回值

示例:

#include<stdio.h>
#include<stdlib.h>

int main()
{
	int ret = 0;
	//打开文件
	FILE* p = fopen("test.txt", "r");
	if (p == NULL)
	{
		printf("打开文件失败\n");
	}


	//设置完文件指针,打印当前文件指针
	fseek(p, 3, SEEK_SET);
	ret = ftell(p);
	printf("%d\n", ret);

	//使用rewind函数将文件指针设置到起始位置
	rewind(p);
	ret = ftell(p);
	printf("%d\n", ret);

	//关闭文件
	fclose(p);
	p = NULL;
	return 0;
}

输出:

3
0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值