C语言之文件操作(1)


文件

  在电脑的D盘,C盘等等中的所有东西都叫文件,在程序设计中,一般有两种文件,一个是程序文件(与程序有关的或者程序产生的),另一个是数据文件(程序运行时读写数据的)。
  一个文件要有一个唯一的文件名,以便识别。文件名一般包含三个部分:文件路径+文件名主干+文件后缀,例如D:\C语言\文件操作.txt,用来存放相关信息

文件的打开和关闭

  对文件进行操作的时候,需要先打开文件,再读/写文件,最后再关闭文件。文件打开时,在内存中创建文件信息区。
  文件信息区的类型是一个FILE类型的,FILE是一个结构体,定义为typedef struct _iobuf FILE,不同的编译器FILE包含的类型不同。通过定义一个FILE*类型的指针变量(例如pf),可以访问文件中的信息。

  C语言中打开文件函数为fopen,MSDN上解释为 FILE *fopen( const char *filename, const char *mode );,第一个变量filename是文件名,第二个变量mode是打开文件的方式。
  打开文件的方式也有很多种,例如‘r’是读,打开一个已经存在了着的文件以输入数据,‘w’是写,打开一个文件输出数据,‘a’是追加,在文本文件末尾追加数据。打开文件成功,返回一个FILE类型的指针,打开文件失败,则返回空指针。


  关闭文件函数为fclose,MSDN上解释为int fclose( FILE *stream );

#include <stdio.h>
#include <stdlib.h>
int main()
{
	FILE* pf = fopen("text.c","r");//相对路径
	//FILE* pf = fopen("D:\\c语言\\Contact\\text.c","r");
	//绝对路径
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return -1;
	}
	else
	{
		printf("打开成功\n");
	}
	fclose(pf);
	return 0;
}

  'r’只能用于读一个已经创建了的文件,如果文件没有创立,可以选择用’w‘的方式创建一个新文件。(z注意’w’只能打开一个空文件,如果文件中已经有类型了,那么就会对内容进行销毁)

FILE* pf = fopen("D:\\c语言\\Contact\\text.c","w");

文件的读写方式

  文件的读写方式有两种,一种是顺序读写,一种是随机读写。

顺序读写函数

fgetc和fputc

函数作用解释适用
fgetc字符输入函数int fgetc( FILE *stream );所有输入流
fputc字符输出函数int fputc( int c, FILE *stream );所有输出流

  流是磁盘或其它外围设备中存储的数据的源点或终点,也就是说通过流,可以将数据操作在文件,屏幕,网站,软件等等上,C语言程序一但运行,就默认打开了三个流,标准输出流(stdout),标准输入流(stdin),标准错误流(stderr),(三者的类型都是FILE*)。

#include <stdio.h>
#include <stdlib.h>
int main()
{
	FILE* pf = fopen("D:\\c语言\\Contact\\text.txt","w");
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return -1;
	}
	else
	{
		printf("打开成功\n");
	}
	fputc('a', pf);//每次写入一个之后指针向后偏移
	fputc('b', pf);
	fputc('c', pf);
	fclose(pf);
	return 0;
}
int main()
{
	FILE* pf = fopen("D:\\c语言\\Contact\\text.txt","r");
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return -1;
	}
	else
	{
		printf("打开成功\n");
	}
	int ch = fgetc(pf);//每次读出后向后偏移
	printf("%d ", ch);
	ch = fgetc(pf);
	printf("%d ", ch);
	ch = fgetc(pf);
	printf("%d ", ch);
	//输出为97 98 99,即a,b,c的ASCII码值
	fclose(pf);
	return 0;
}

fputs和fgets

函数作用解释适用
fgets文本行输入函数char *fgets( char *string, int n, FILE *stream );所有输入流
fputs文本行输出函数int fputs( const char *string, FILE *stream );所有输出流
int main()
{
	FILE* pf = fopen("D:\\c语言\\Contact\\text.txt","w");
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return -1;
	}
	else
	{
		printf("打开成功\n");
	}
	fputs("hello\n", pf);
	fputs("world!\n", pf);
	fclose(pf);
	return 0;
}

  写入操作后在文本文件中显示hello world。
  char *fgets( char *string, int n, FILE *stream );函数中第一个参数是字符串,读取文件中的字符串放在该字符串中。n是读取的个数,stream是文件指针。

int main()
{
	FILE* pf = fopen("D:\\c语言\\Contact\\text.txt","r");
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return -1;
	}
	else
	{
		printf("打开成功\n");
	}
	char arr[20] = { 0 };
	fgets(arr,5, pf);
	printf("%s\n", arr);
	fgets(arr,5, pf);//再次读取时,覆盖arr
	printf("%s\n", arr);
	fclose(pf);
	return 0;
}

  文件中的数据为hello world,读取后这里显示为

  函数读取5个元素,但是实际上读取的只有4个,最后一位自动置为\0,所以显示如上。

fscanf和fprintf

函数作用解释适用
fscanf格式化输入函数int fscanf( FILE *stream, const char *format [, argument ]… );所有输入流
fprintf格式化输出函数int fprintf( FILE *stream, const char *format [, argument ]…);所有输出流

  对比printf和fprintf,scanf在MSDN上解释为 int printf( const char *format [,argument]… );,fprintf相对于printf来说多了一个参数FILE *stream。

struct Data
{
	int x;
	float y;
};
int main()
{
	struct Data data = { 5,2.4 };
	FILE* pf = fopen("D:\\c语言\\Contact\\text.txt","w");
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return -1;
	}
	else
	{
		printf("打开成功\n");
	}
	//写文件
	fprintf(pf, "%d %f", data.x, data.y);
	fclose(pf);
	return 0;
}

  对比scanf和fscanf,scanf在MSDN上解释为 int scanf( const char *format [,argument]… );,fscanf相对于scanf来说多了一个参数FILE *stream。

struct Data
{
	int x;
	float y;
};
int main()
{
	struct Data data = { 0 };
	FILE* pf = fopen("D:\\c语言\\Contact\\text.txt","r");
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return -1;
	}
	else
	{
		printf("打开成功\n");
	}
	//读取数据
	fscanf(pf, "%d %f", &(data.x), &(data.y));
	printf("%d %f", data.x, data.y);
	fclose(pf);
	return 0;
}

fread和 fwrite

函数作用解释适用
fread二进制输入函数size_t fread( void *buffer, size_t size, size_t count, FILE *stream );文件
fwrite二进制输出函数size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );文件

  fwrite函数中,buffer指向被写的数据,size是要写的元素的大小,单位是字节,count是要写的个数,stream是文件指针。

struct Data
{
	int x;
	float y;
	char z;
};
int main()
{
	struct Data data = {1,2.4,'a'};
	FILE* pf = fopen("D:\\c语言\\Contact\\text.txt","wb");
	//wb是以二进制的方式进行只写操作
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return -1;
	}
	else
	{
		printf("打开成功\n");
	}
	fwrite(&data, sizeof(struct Data), 1, pf);
	fclose(pf);
	return 0;
}

  这个时候在文本文件中的显示如下,因为fwrite是以二进制的形式进行存储的,所以在文件中的显示方式也是二进制的形式,

  fread函数和fwrite类似,buffer指向被存入数据的地址,size是要读的元素的大小,count是要读的个数,stream是文件指针。

struct Data
{
	int x;
	float y;
	char z;
};
int main()
{
	struct Data data = {0};
	FILE* pf = fopen("D:\\c语言\\Contact\\text.txt","rb");
	//rb是以二进制的形式读
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return -1;
	}
	else
	{
		printf("打开成功\n");
	}
	fread(&data, sizeof(struct Data), 1, pf);
	printf("%d %f %c", data.x, data.y, data.z);
	fclose(pf);
	return 0;
}

  此时的显示为,

sscanf和sprintf

函数作用解释
sscanf读一个格式化的数据到字符串int sscanf( const char *buffer, const char *format [, argument ] … );
sprintf写一个格式化的数据到字符串int sprintf( char *buffer, const char *format [, argument] … );
struct Data
{
	int x;
	float y;
	char z;
};
int main()
{
	struct Data data = { 1, 2.4, 'a' };
	char arr[100] = { 0 };
	sprintf(arr,"%d %f %c",data.x, data.y, data.z );
	printf("%s", arr);
	return 0;
}

  sprintf即把一个格式化的数据(data.x, data.y, data.z)转换到了arr字符串里面。

#include <stdio.h>
#include <stdlib.h>
struct Data
{
	int x;
	float y;
	char z;
};
int main()
{
	struct Data data1 = { 1, 2.4, 'a' };
	struct Data data2 = { 0 };
	char arr[100] = { 0 };
	sprintf(arr,"%d %f %c",data1.x, data1.y, data1.z );
	sscanf(arr, "%d %f %c", &(data2.x), &(data2.y), &(data2.z));
	//从arr1字符串中提取一个格式化的数据
	printf("%d %f %c", data2.x, data2.y, data2.z);
	return 0;

随机读写函数

fseek

  feek为随机读取函数,可以将文件指针移动到指定的位置。在MSDN上解释为int fseek( FILE *stream, long offset, int origin );,origin为文件的位置,MSDN上定义了文件指针的相关位置,SEEK_CUR为文件的当前位置,SEEK_END为文件的末尾位置,SEEK_SET为文件的起始位置。

int main()
{
	FILE* pf = fopen("D:\\c语言\\Contact\\text.txt", "r");
	if (pf == NULL)
	{
		perror("失败");
		return -1;
	}
	fseek(pf, 2, SEEK_SET);
	int ch = fgetc(pf);
	printf("%c", ch);
	//c读取完成之后向后偏移了一位
	fseek(pf, -2, SEEK_CUR);
	ch = fgetc(pf);
	printf("%c", ch);
	return 0;
}

  设原始数据为abcd,输出为cd。

ftell

  ftell函数可以用来计算文件指针相对于起始位置的偏移量。MSDN上解释为long ftell( FILE *stream );

int main()
{
	FILE* pf = fopen("D:\\c语言\\Contact\\text.txt", "r");
	if (pf == NULL)
	{
		perror("失败");
		return -1;
	}
	fseek(pf, 2, SEEK_SET);
	int ch = fgetc(pf);
	printf("%c", ch);
	int x = ftell(pf);
	printf("%d", x);
	//输出为3
	return 0;
}

rewind

  rewind函数是让文件指针回到文件的起始位置。在MSDN上解释为void rewind( FILE *stream );

int main()
{
	FILE* pf = fopen("D:\\c语言\\Contact\\text.txt", "r");
	if (pf == NULL)
	{
		perror("失败");
		return -1;
	}
	fseek(pf, 2, SEEK_SET);
	int ch = fgetc(pf);
	printf("%c", ch);
	rewind(pf);
	//回到起始位置
	ch = fgetc(pf);
	printf("%c", ch);
	//设文件中为abcd,打印为a
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值