首页 > 其他分享 >【零基础C语言】文件操作

【零基础C语言】文件操作

时间:2024-03-29 21:30:49浏览次数:22  
标签:文件 NULL int C语言 pf FILE 操作 txt

目录

 理解文件操作

 什么是文件

 程序文件

 数据文件

 文件名字

 二进制文件和文本文件

 文件的打开和关闭

 文件的打开和关闭操作

实验1,打开一个文件并且输入26个字母 

打开读取文件text.txt ,并且将它拷贝进text_cpy.txt 

使用 fputs 和 fgets 函数 

使用 fprintf函数和 fscanf 函数 

有关于流的概念

 使用 fwrite 和 fread 函数

文件的随机读写 - 适用于二进制文件

 fseek 函数

ftell 函数 

 rewind 函数

 文件读取结束的判定

文件缓冲区


 

 理解文件操作

 我们为什么要使用文件呢?

 1.可以长久的存储我们的数据,没有文件存储我们输入的程序代码数据是在电脑内存中存储的,但是程序结束后,我们的数据也会清空,无法持久化保存

如以下代码:

int main()
{
	int a = 0; //创建变量a
	scanf("%d", &a); // 向a中输入数值
	return 0;
}

 我们可以通过内存窗口看见int变量a中存放我们输入的值,但是程序结束,数据会清空,我们需要重新输入

 什么是文件

 文件指的就是磁盘上的文件
 但是程序中我们的文件分为两种:程序文件,数据文件 - 按照功能划分

 

 程序文件


 struct 程序文件
{
    1.源程序文件(后缀为.c);
  2.目标文件(windows环境后缀为.obj);
  3.可执行文件(windows环境后缀为.exe);
};

 数据文件


 该文件的内容不一定是程序,也可以是运行时读写的数据,比如程序运⾏需要从中读取数据的⽂件,或者输出内容的文件。


 文件名字


 用于用户识别和使用,是文件的标识,这个相信大家都不陌生,我们在打开磁盘可以在上方的小方块看到当期文件的名字。

 二进制文件和文本文件

根据数据不同形式,我们将数据文件划分为二进制文件和文本文件

二进制文件:以二进制的形式存储,不用转换直接可以输出到外存

文本文件:字符一律以ASCLL码值存储,需要转换才可以输出到外存
 

 文件的打开和关闭

 在了解文件之前,我们需要认识一种抽象的概念 - 流
 什么是流呢?我们在生活中获取消息是从人流,网上等等渠道,同理计算机也是如此,
 我们把从键盘输入,文件读写和其他所有外部的数据糅合起来比作一条流淌着字符的数据河,
 而计算机则是从河中获取所需要的数据,读取它们,然后打开,再操作数据

 那么我们有可能有疑问了?我们平时键盘输入代码,屏幕打印字符数据好像并没有使用流啊
 这里我们就需要引入一个概念 - 标准流


 标准流在计算机C程序运行启动时就默认打开了3个流:

  1. stdin  - 标准输入流,获取我们输入的信息。
  2. stdout - 标准输出流,输出我们需要打印的信息
  3. stderr - 标准错误流。

 有了以上默认打开的流,我们使用scanf和printf就可以进行输入输出操作

 stdin,stdout,stderr 类型为 FILE* - 文件指针
 C语⾔中,就是通过FILE*的⽂件指针来维护流的各种操作的。

 文件指针

 我们在打开使用文件时,内存中会开辟一个文件信息区,这个信息区用来存放文件的相关
 信息,这些信息是保存在一个结构体变量中,取名为FILE。

 如vs2013编译环境中#include <stdio.h> 头文件种的类型申明。

struct _iobuf {
	char* _ptr;
	int _cnt;
	char* _base;
	int _flag;
	int _file;
	int _charbuf;
	int _bufsiz;
	char* _tmpfname;
};
typedef struct _iobuf FILE;

 借助这点我们可以定义一个指针变量指向该文件信息区,间接的找到该文件

 FILE* pf; 文件指针变量


 文件的打开和关闭操作

 在读写编辑文件之前,我们需要学会如何打开和关闭文件

 1.打开文件

 在编写程序时在打开⽂件的同时,都会返回⼀个FILE*的指针变量指向该⽂件,也相当于建⽴了
 指针和⽂件的关系。

 ANSIC规定使⽤ fopen 函数来打开⽂件, fclose 来关闭⽂件

 代码演示:

 打开文件:
FILE* fopen(const char* filename, const char* mode);

 关闭文件:
int fclose(FILE* stream);

 mode - 文件打开的模式,所有模式如下:

 "r"(只读) - 输入数据,打开一个存在的文本文件 - 如果文件不存在(出错)

 "w"(只写) - 输出数据,打开一个文本文件 - 如果文件不存在(创建一个新的文件)

 "a"(追加) - 向文本文件末尾添加数据 - 如果文件不存在(创建一个新的文件)

 "rb"(只读) - 输入数据,打开一个二进制文本文件 - 如果文件不存在(出错)

 "wb"(只写) - 输出数据,打开一个二进制文本文件 - 如果文件不存在(创建一个新的文件)

 "ab"(追加) - 向二进制文本文件末尾添加数据 - 如果文件不存在(创建一个新的文件)

 "r+"(读写) - 为了读和写,打开一个文本文件 - 如果文件不存在(出错)

 "w+"(读写)- 为了读和写,创建一个文本文件 - 如果文件不存在(创建一个新的文件)

 "a+"(读写)- 打开一个文本文件,在文件末尾进行读写 - 如果文件不存在(创建一个新的文件)

 "rb+"(读写)- 为了读和写,打开一个二进制文本文件 - 如果文件不存在(出错)

 "wb+"(读写)- 为了读和写,创建一个二进制文本文件 - 如果文件不存在(创建一个新的文件)

 "ab+"(读写)- 打开一个二进制文本文件,在文件末尾进行读写 - 如果文件不存在(创建一个新的文件)
int main()
{
	// 创建文本指针变量
	FILE* pf;
	//打开文件
	pf = fopen("text.txt", "r");
	//文件操作
	if (pf == NULL)
	{
		//...
		perror("fopen");
		return 1;
	}
	else
	{
		fclose(pf);
		pf = NULL;
	}
	return 0;
}
 文件的顺序读写

 1.顺序读写函数介绍

  函数    功能          适用于

 fgetc - 字符输入函数 - 所有的输入流

 fputc - 字符输出函数 - 所有的输出流

 fgets - 文本行输入函数 - 所有输入流

 fputs - 文本行输入函数 - 所有输入流

 fscnaf - 格式化输入函数 - 所有输入流

 fprintf - 格式化输出函数 - 所有输出流

 fread   -   二进制输入   -   文件

 fwrite   -   二进制输出   -   文件

实验1,打开一个文件并且输入26个字母 

// 实验1,打开一个文件并且输入26个字母

int main()
{
	// 打开并且写一个文件 - "w"
	FILE* pf = fopen("text.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	//写文件
	int ch = 0;
	for (ch = 'a'; ch <= 'z'; ch++)
	{
		fputc(ch, pf);
	}

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

打开读取文件text.txt ,并且将它拷贝进text_cpy.txt 

// 打开读取文件text.txt ,并且将它拷贝进text_cpy.txt

int main()
{
	// 打开文件
	FILE* pf = fopen("text.txt", "r");
	if (pf == NULL)
	{
		perror("fopen text.txt");
		return 1;
	}

	FILE* pw = fopen("text_cpy.txt", "w");
	if (pw == NULL)
	{
		perror("fopen text_cpy.txt");
		fclose(pf);
		pf = NULL;
		return 1;
	}

	// 读取并且写入
	int ch = 0;
	while ((ch = fgetc(pf)) != EOF)
	{
		fputc(ch, pw);
	}

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

使用 fputs 和 fgets 函数 

//使用 fputs 和 fgets 函数

int main()
{
	// 打开文件
	FILE* pf = fopen("fputs.txt", "w");
	if (pf == NULL)
	{
		perror("fopen fputs.txt");
		return 1;
	}

	// 使用 fputs函数写文件
	// 函数原型
	// int fputs(const char* str, FILE * stream);
	// const char* str 传入读取的字符串的首地址
	// FILE* stream 将读取的内容写入文件中

	char ch[] = "ouyang is cool\n";
	fputs(ch, pf);
	fputs("hello ouyang", pf);

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


int main()
{
	// 打开文件
	FILE* pf = fopen("fputs.txt", "r");
	if (pf == NULL)
	{
		perror("fopen fputs.txt");
		return 1;
	}

	// 使用 fgets函数读取文件
	// 函数原型
	// char* fgets(char* str, int num, FILE * stream);
	// char* str 函数将读取到的数据返回char*类型指针的首地址
	// int num  读取的长度
	// FILE* stream 读取文件的地址
	// 如果读取失败会返回NULL

	char ch[20] = { 0 };

	// 单个读取
	/*fgets(ch, 20, pf);
	printf("%s", ch);*/

	// 连续读取
	while (fgets(ch, 20, pf) != NULL)
	{
		printf("%s", ch);
	}
	
	// 关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

使用 fprintf函数和 fscanf 函数 

typedef struct stu
{
	char name[20];
	int age;
	char sex[5];
}S;

int main()
{
	// 打开文件并且写入
	FILE* pf = fopen("fprintf.txt", "w");
	if (pf == NULL)
	{
		perror("fopen fprintf.txt");
		return 1;
	}

	// 写入
	S s = { "欧阳",20,"男" };
	fprintf(pf, "%s %d %s", s.name, s.age, s.sex);


	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}
typedef struct stu
{
	char name[20];
	int age;
	char sex[5];
}S;
int main()
{
	// 打开文件并且写入
	FILE* pf = fopen("fprintf.txt", "r");
	if (pf == NULL)
	{
		perror("fopen fprintf.txt");
		return 1;
	}

	// 读取文件
	S s = {0};
	fscanf(pf, "%s %d %s", s.name, &(s.age), s.sex);

	// 打印在屏幕上观察
	printf("%s %d %s", s.name, s.age, s.sex);

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

有关于流的概念

  • stdin - 标准输入流,获取我们输入的信息。
  • stdout - 标准输出流,输出我们需要打印的信息
  • fgetc, fgets, fputc, fputs, fscanf, fprintf - 适用于所有流
  • fread, fwrite - 适用于文件流
// 使用标准流

int main()
{
	fputc('a', stdout);
	return 0;
}

 使用 fwrite 和 fread 函数

 

int main()
{
	// 以二进制的形式写文件
	FILE* pf = fopen("fwrite.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen fwrite.txt");
		return 1;
	}

	// 写二进制文件

	// fwrite 函数
	// 函数原型:
	// size_t fwrite(const void* ptr, size_t size, size_t count, FILE * stream);
	// const void* ptr - 指向要写入文件的数据
	// size_t size - 指向数据类型的大小
	// siez_t count -指向数据的数量
	// FILE * stream - 写入的文件指针

	int arr[] = { 1,2,3,4,5 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	fwrite(arr, sizeof(arr[0]), sz, pf);

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

int main()
{
	// 打开文件
	FILE* pf = fopen("fwrite.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen fwrite.txt");
		return 1;
	}

	// 读取文件
	// fread 函数
	// 函数原型:
	// size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
	// const void* ptr - 指向要读取文件的数据
	// size_t size - 指向数据类型的大小
	// siez_t count -指向数据的数量
	// FILE * stream - 要读取的文件指针
	int arr[5] = { 0 };
	fread(arr, sizeof(arr[0]), 5, pf);
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%d ", arr[i]);
	}

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

文件的随机读写 - 适用于二进制文件

 fseek 函数

// 函数原型:
// int fseek ( FILE * stream, long int offset, int origin );

// FILE * stream - 指向FILE*文件对象的指针
// long int offset - 偏移的字节数
// int origin - 参考位置
// 如:
//SEEK_SET	文件开头
//SEEK_CUR	文件指针的当前位置
//SEEK_END	文件末尾*


int main()
{
	// 读写文件
	FILE* pf = fopen("fseek.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen fseek.txt");
		return 1;
	}

	// 读写
	fputs("hello ouyang",pf);
	fseek(pf, 6, SEEK_SET);
	fputs("to ", pf);

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

int main()
{
	// 打开并且读文件
	FILE* pf = fopen("fseek.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen fseek.txt");
		return 1;
	}

	// 读取文件
	char ch[200] = { 0 };
	while (fgets(ch, 50, pf) != NULL)
	{
		printf("%s\n", ch);
	}

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

ftell 函数 

// 函数原型:
// long int ftell ( FILE * stream );

int main()
{
	// 读写文件
	FILE* pf = fopen("fseek.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen fseek.txt");
		return 1;
	}

	// ftell 函数的使用
	fseek(pf, 6, SEEK_SET);
	long size = ftell(pf);
	printf("Size of myfile.txt: %ld bytes.\n", size);

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

 rewind 函数

// 函数原型:
// void rewind ( FILE * stream );

int main()
{

	// 打开文件并且写入
	FILE* pf = fopen("myfile.txt", "w+");
	char buffer[27];
	int n = 0;
	for (n = 'A'; n <= 'Z'; n++)
		fputc(n, pf); //写入之后的光标在最后
	rewind(pf); // 回调光标
	fread(buffer, 1, 26, pf); // 将文件中的数据读取到字符数组中

	//关闭文件
	fclose(pf);
	pf = NULL;

	// 打印观察
	buffer[26] = '\0'; // 方便输出字符串,将最后一位设置为'\0'
	printf(buffer); // 打印
	return 0;
}

 文件读取结束的判定

 feof 函数
 注意:该函数不可以通过该函数的返回值来直接判断文件的结束

 作用是当文件结束时,判断是读取失败的原因,还是遇到文件结尾结束

⽂本⽂件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )
例如:
• fgetc 判断是否为 EOF 
• fgets 判断返回值是否为 NULL 

int main()
{
	int c = 0; // 注意:int,⾮char,要求处理EOF
	FILE* fp = fopen("test.txt", "r");
	if (fp==NULL) 
	{
		perror("File opening failed");
		return 1;
	}


	//fgetc 当读取失败的时候或者遇到⽂件结束的时候,都会返回EOF
	while ((c = fgetc(fp)) != EOF) // 标准C I/O读取⽂件循环
	{
		putchar(c);
	}


	//判断是什么原因结束的
	if (ferror(fp))
		puts("I/O error when reading");
	else if (feof(fp))
		puts("End of file reached successfully");
	fclose(fp);
	fp = NULL;
}

文件缓冲区

我们在程序中向文件中写入数据不会是有一条写一条,打个比方说:一个学生
问问题不是说问完一个过几分钟又问一个,则会导致老师无法为其他同学解答
问题,操作系统也是如此,操作系统不光是为了写入文件而服务的,所有这个学生
就会将问题攒着,直到一定的数量就可以去问老师,同理我们写入的文件也是如此
而存放这些数据的空间就叫做文件缓冲区

源代码地址:text_2024_3_26 · 6988b68 · 阳区欠/C语言学习路程 - Gitee.com

标签:文件,NULL,int,C语言,pf,FILE,操作,txt
From: https://blog.csdn.net/2301_81577798/article/details/137056371

相关文章

  • 【零基础C语言】预处理解析
     预定义符号 c语言中设置一些预定的符号,我们可以直接使用//列:__FILE__//进⾏编译的源⽂件__LINE__//⽂件当前的⾏号__DATE__//⽂件被编译的⽇期__TIME__//⽂件被编译的时间__STDC__//如果编译器遵循ANSIC,其值为1,否则未定义 /续行符号intmain(){ printf......
  • 【零基础C语言】动态内存管理
     目录1.动态内存分配的意义 2.malloc函数 3.free函数 4.calloc函数 5.realloc函数 6.常见的动态内存错误 6.1对NULL指针的解引⽤操作6.2对动态开辟空间的越界访问6.3对非动态开辟内存使⽤free释放 6.4使⽤free释放⼀块动态开辟内存的⼀部分 6.5......
  • python 脚本对数据库的简单操作
    importsqlite3fromdatetimeimportdatetime'''数据库内容[ID]intnull,[loginName]text(50),[loginTime]text(50),[logOutTime]text(50),[operation]intnull'''#连接到数据库conn=sqlite3.connect('test.......
  • 第16期 Double Commander 开源免费的Total Commander替代型【体验100款文件管理工具】
     体验背景:我们正在做一款文件版本管理软件,追光几何(追光几何),期待以最无感的方式,解决新一代工程师文件管理的问题,让大家有更多时间去做快乐和有成就感的事情。所以打算体验100款文件管理软件,来取长补短。真实1h体验DoubleCommander是一款开源的跨平台文件管理软件,灵感来源......
  • DOM(文档对象模型):理解网页结构与内容操作的关键技术
    DOM(文档对象模型)定义了一种访问和操作文档的标准。它是一个平台和语言无关的接口,允许程序和脚本动态访问和更新文档的内容、结构和样式。HTMLDOM用于操作HTML文档,而XMLDOM用于操作XML文档。HTMLDOM示例通过ID获取并修改HTML元素的值:<!DOCTYPEhtml><html><head><style>......
  • 用C语言实现汉诺塔游戏
    汉诺塔游戏。游戏目标是将A柱子上的盘子移动到C柱子上,且每次小的盘子要放在大的盘子上面。如只有一个盘子则直接移至C柱子。以如图所示为例子。3个盘子要移动至C柱子,具体步骤为:A到C,A到B,C到B,A到C,B到A,B到C,A到C。总共7步。也就是先把A柱子两个盘子(n-1)通过C柱子移......
  • 简单介绍c语言程序的编译与链接
    程序运行的背后程序在运行时经历了四个步骤,分别是预编译(Prepressing)、编译(Compilation)、汇编(Assembly)和链接(Linking)。预编译预编译也称预处理,源代码文件(.c)和相关的头文件(.h)等被预编译器cpp预编译成一个.i文件。编译编译过程就是将预处理后的文件进行一系列......
  • 操作系统实验6之信号量的实现与应用
    操作系统中常用信号量相关系统调用函数用法1、sem_open:用于创建或打开一个命名的信号量。点击查看代码#include<semaphore.h>sem_t*sem_open(constchar*name,intoflag,mode_tmode,unsignedintvalue);name:信号量的名称,必须以斜杠开头,例如/my_semaphore。oflag:......
  • //拷贝文件夹 //将file1文件夹中的数据拷贝到文件夹file2中
    //拷贝文件夹//将file1文件夹中的数据拷贝到文件夹file2中publicclassFileDemo1{publicstaticvoidmain(String[]args)throwsIOException{//拷贝文件夹//将file1文件夹中的数据拷贝到文件夹file2中Filefile1=newFile("D:\\file......
  • 文件-Python
    师从黑马程序员文件编码 不同编码,将内容翻译成二进制也是不同的查看文件编码文件的读取文件的概念文件操作内容主要包括打开,关闭,读,写文件的操作步骤open()打开函数mode常用的三种基础访问模式读操作相关方法读操作相关方法close()关闭文件对象wi......