首页 > 其他分享 >⽂件操作函数

⽂件操作函数

时间:2024-03-28 23:30:01浏览次数:18  
标签:NULL return 函数 int pf FILE 操作 fopen

1. 流和标准流

1.2 流

我们程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同的外部设备的输⼊输出 操作各不相同,为了⽅便程序员对各种设备进⾏⽅便的操作,我们抽象出了流的概念,我们可以把流 想象成流淌着字符的河。 C程序针对⽂件、画⾯、键盘等的数据输⼊输出操作都是通过流操作的。 ⼀般情况下,我们要想向流⾥写数据,或者从流中读取数据,都是要打开流,然后操作。

1.3 标准流

1. stdin- 标准输⼊流,在⼤多数的环境中从键盘输⼊,scanf函数就是从标准输⼊流中读取数据。 

2.  stdout- 标准输出流,⼤多数的环境中输出⾄显⽰器界⾯,printf函数就是将信息输出到标准输出 流中。

 3.  stderr- 标准错误流,⼤多数环境中输出到显⽰器界⾯。

 这是默认打开了这三个流,我们使⽤scanf、printf等函数就可以直接进⾏输⼊输出操作的。 stdin、stdout、stderr三个流的类型是: FILE* ,通常称为⽂件指针。 C语⾔中,就是通过 FILE* 的⽂件指针来维护流的各种操作的。

1.4 ⽂件指针

       缓冲⽂件系统中,关键的概念是“⽂件类型指针”,简称“⽂件指针”。 每个被使⽤的⽂件都在内存中开辟了⼀个相应的⽂件信息区,⽤来存放⽂件的相关信息(如⽂件的名字,⽂件状态及⽂件当前的位置等)。这些信息是保存在⼀个结构体变量中的。该结构体类型是由系 统声明的,取名FILE.

1.5 ⽂件的打开和关闭

     ⽂件在读写之前应该先打开⽂件,在使⽤结束之后应该关闭⽂件。 在编写程序的时候,在打开⽂件的同时,都会返回⼀个FILE*的指针变量指向该⽂件,也相当于建⽴了 指针和⽂件的关系。 ANSIC规定使⽤ fopen 函数来打开⽂件, fclose 来关闭⽂件。

//打开⽂件 
FILE * fopen ( const char * filename, const char * mode );
//关闭⽂件 
int fclose ( FILE * stream );

 mode表⽰⽂件的打开模式,下⾯都是⽂件的打开模式:

 

/* fopen fclose example */
#include <stdio.h>
int main ()
{
 FILE * pFile;
 //打开⽂件 
 pFile = fopen ("myfile.txt","w");
 //⽂件操作 
 if (pFile!=NULL)
 {
 fputs ("fopen example",pFile);
 //关闭⽂件 
 fclose (pFile);
 }
 return 0;
}

 1.6顺序读写函数介绍

 上⾯说的适⽤于所有输⼊流⼀般指适⽤于标准输⼊流和其他输⼊流(如⽂件输⼊流);所有输出流⼀ 般指适⽤于标准输出流和其他输出流(如⽂件输出流)。

1.6.1 函数详解

fgetc函数

fgetc 从文件流中获取字符

#include<stdio.h>

int main()
{
	FILE* pf = fopen("test2.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	
	int ch = 0;
	while ((ch = fgetc(pf)) != EOF)
	{
		printf("%c", ch);
	}

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

fputc 函数

 fputc("写入的字符",文件流的指针);

#include<stdio.h>

int main()
{
	FILE* pf = fopen("test2.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	char ch = 0;
	for (ch = 'a'; ch < 'z'; ch++)
	{
		fputc(ch, pf);
	}


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

fgets 函数

 fgets(读取文本存放的数组,读取文本的个数,所在的文件流的指针)

 

#include<stdio.h>

int main()
{
	FILE* pf = fopen("test2.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	char arr[100] = { 0 };//先定义一个字符的数组

	while (fgets(arr, 100, pf) != NULL);
	{
		printf("%s", arr);
	}

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

fputs 函数

 fputs("被写入的文本",对应的文件流)

#include<stdio.h>

int main()
{
	FILE* pf = fopen("test2.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	fputs("hello world\n", pf);
	fputs("relax youself\n", pf);

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

fscanf 函数

 fscanf(对应的文件流指针 ,  相应的占位符,例如:%s %d %f ,占位符对应的变量)

#include<stdio.h>
struct S
{
	char name[20];
	int age;
	float score;
};

int main()
{
	struct S s = { "张三",20,65.5f };
	FILE* pf = fopen("data.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	fscanf(pf, "%s %d %f\n", s.name, &(s.age), &(s.score));//读,char类型的不用&
	printf("%s %d %f\n", s.name, s.age, s.score);

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

 fprintf 函数

 fprintf(对应的文件流指针,写入内容对应的占位符,写入内容对应的变量)

#include<stdio.h>
struct S
{
	char name[20];
	int age;
	float score;
};

int main()
{
	struct S s = { "张三",20,65.5f };
	FILE* pf = fopen("data.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	fprintf(pf, "%s %d %f", s.name, s.age, s.score);//写

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

fread 函数

 fread(读取文件后放在的数组arr ,每个元素的大小sizeof(int[0]) ,几个元素 , 文件流对应的指针)

 

#include<stdio.h>

int main()
{
	int arr[] = { 1,2,3,4,5 };

	FILE* pf = fopen("data.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	fread(arr, sizeof(arr[0]), 5, pf);
	int a = 0;
	for (a = 0; a < 5; a++)
	{
		printf("%d ", arr[a]);
	}

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

fwrite 函数

 fwrite(写文件后放在的数组arr ,每个元素的大小sizeof(int[0]) ,几个元素sizeof(arr)/sizeof(int[0]), 文件流对应的指针)

 

#include<stdio.h>

int main()
{
	int arr[] = { 1,2,3,4,5 };

	FILE* pf = fopen("data.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	int sz = sizeof(arr) / sizeof(arr[0]);
	fwrite(arr, sizeof(arr[0]), sz, pf);

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

 1.7 对⽐⼀组函数:

1. scanf/fscanf/sscanf

2. printf/fprintf/sprintf

1.1 scanf 从标准输入流中读取格式化数据

1.2  fscanf 从指定的标准输入流中读取格式化的数据

1.3 sscanf 在字符串中读取格式化的数据

 

#include<stdio.h>
struct S
{
	char name[20];
	int age;
	float score;
};

int main()
{
	char buf[200] = { 0 };
	struct S s = { "张三",20,65.5f };
	sprintf(buf, "%s %d %f", s.name, s.age, s.score);
	printf("1.以字符串的形式:%s\n", buf);

	struct S t = { 0 };
	sscanf(buf, "%s %d %f", t.name, &(t.age), &(t.score));
	printf("2.按照格式打印:   %s %d %f", t.name, t.age, t.score);

	return 0;
}

 2.1 printf 把数据以格式化的形式打印在标准输出流上

2.2 fprintf 把数据以格式化的形式打印在指定的标准输出流上

2.3 sprintf 把数据转化为字符串

 

#include<stdio.h>
struct S
{
	char name[20];
	int age;
	float score;
};

int main()
{
	char buf[200] = { 0 };
	struct S s = { "张三",20,65.5f };
	sprintf(buf, "%s %d %f", s.name, s.age, s.score);
	printf("1.以字符串的形式:%s\n", buf);

	struct S t = { 0 };
	sscanf(buf, "%s %d %f", t.name, &(t.age), &(t.score));
	printf("2.按照格式打印:   %s %d %f", t.name, t.age, t.score);

	return 0;
}

 2. ⽂件的随机读写

2.1 fseek函数

根据⽂件指针的位置和偏移量来定位⽂件指针。

fseek(文件流对应的指针,偏移量,起始位置)

1. SEEK_SET 文件的起始位置

2. SEEK_CUR 文件指针的当前位置

3. SEEK_END 文件的末尾

 

#include<stdio.h>

int main()
{
	FILE* pf = fopen("data.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	int ch = fgetc(pf);
	printf("%c\n", ch);

	fseek(pf, 4, SEEK_CUR);
	fseek(pf, 5, SEEK_SET);
	fseek(pf, -4,SEEK_END);

	ch = fgetc(pf);
	printf("%c\n", ch);

	fclose(pf);
	pf = NULL;

	return 0;
}

2.2 ftell 函数

返回⽂件指针相对于起始位置的偏移量

 

/* ftell example : getting size of a file */
#include <stdio.h>
int main ()
{
 FILE * pFile;
 long size;
 pFile = fopen ("myfile.txt","rb");
 if (pFile==NULL) 
 perror ("Error opening file");
 else
 {
 fseek (pFile, 0, SEEK_END); // non-portable
 size=ftell (pFile);
 fclose (pFile);
 printf ("Size of myfile.txt: %ld bytes.\n",size);
 }
 return 0;
}

2.3 rewind函数

 

/* rewind example */
#include <stdio.h>
int main ()
{
 int n;
 FILE * pFile;
 char buffer [27];
 
 pFile = fopen ("myfile.txt","w+");
 for ( n='A' ; n<='Z' ; n++)
 fputc ( n, pFile);
 rewind (pFile);
 
 fread (buffer,1,26,pFile);
 fclose (pFile);
 
 buffer[26]='\0';
 printf(buffer);
 return 0;
}

3. ⽂件读取结束的判定

3.1 被错误使⽤的 feof 

牢记:在⽂件读取过程中,不能⽤feof函数的返回值直接来判断⽂件的是否结束。

feof 的作⽤是:当⽂件读取结束的时候,判断是读取结束的原因是否是:遇到⽂件尾结束。

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

例如:

• fgetc 判断是否为 EOF .

 • fgets 判断返回值是否为 NULL .

3.2. ⼆进制⽂件的读取结束判断,判断返回值是否⼩于实际要读的个数。

例如: • fread判断返回值是否⼩于实际要读的个数。

⽂本⽂件的例⼦:

#include <stdio.h>
#include <stdlib.h>
 
int main(void)
{
 int c; // 注意:int,⾮char,要求处理EOF 
 FILE* fp = fopen("test.txt", "r");
 if(!fp) {
 perror("File opening failed");
 return EXIT_FAILURE;
 }
 //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);
}

⼆进制⽂件的例⼦:

#include <stdio.h>
 
enum { SIZE = 5 };
int main(void)
{
 double a[SIZE] = {1.,2.,3.,4.,5.};
 FILE *fp = fopen("test.bin", "wb"); // 必须⽤⼆进制模式 
 fwrite(a, sizeof *a, SIZE, fp); // 写 double 的数组 
 fclose(fp);
 double b[SIZE];
 fp = fopen("test.bin","rb");
 size_t ret_code = fread(b, sizeof *b, SIZE, fp); // 读 double 的数组 
 if(ret_code == SIZE) {
 puts("Array read successfully, contents: ");
 for(int n = 0; n < SIZE; ++n) 
 printf("%f ", b[n]);
 putchar('\n');
 } else { // error handling
 if (feof(fp))
 printf("Error reading test.bin: unexpected end of file\n");
 else if (ferror(fp)) {
 perror("Error reading test.bin");
 }
 }
 
 fclose(fp);
}

标签:NULL,return,函数,int,pf,FILE,操作,fopen
From: https://blog.csdn.net/2302_81357520/article/details/137125433

相关文章

  • Qt5.14.2 无所不能的Qt数据库操作之旅
    身为程序员,数据库无疑是我们最为亲密无间的好伙伴。但如何高效地操作数据库,却一直是一个令人颇感棘手的难题。不过,没关系,我们的Qt大神们早已为此开辟出一条华丽绝伦的大道,就让我带你一览他们的绝世数据库操作艺术吧!一、查询驱动,方能驱车万里在对数据库开展操作之前,我......
  • 第十一章 :Linux 进阶finalshell操作
    指令不会可以后面加--help 例如find--help1)数据输出echo格式 echo数据 将数据输出展示到终端界面列入 echo helloworld 将会输出 helloworldecho pwd 将会只输出pwd(pwd当作文字输出)则echo·pwd·(ESC下面的反引号)输出的是当前目录 ......
  • Golang操作kafka遇到网络问题重试的案例
    草稿0、实际中会遇到网络抖动会导致消费者有一小段时间与kafka连接遇到问题~0、如何模拟网络问题?本地跑多个kafka实例直接关掉其中一个kafka服务??怎么模拟断网??1、kafka-go与sarama都演示一下2、一个consumer消费一个topic的例子;模拟网络问题可以把kafka服务关了~观察一下再开启k......
  • 操作符重载(operator overloading)
    操作符重载(operatoroverloading)成员函数所有的成员函数一定带着一个隐藏的参数示例代码:inlinecomplex&complex::operator+=(constcomplex&r){//调用者就是this,这是一个指针.+=符号作用在左边的数,左边的数就是this.->编译器自动会传入c2的指针//this......
  • 二、Linux 常见终端操作 Shell 指令总结
    Shell指令总结Linux终端是许多开发人员、系统管理员和技术爱好者经常使用的工具之一。通过掌握Shell指令,可以高效地管理文件系统、执行任务和配置系统。本篇博客简单总结了Linux常见终端操作的Shell指令,帮助大家快速掌握基本操作和提高工作效率。文件和目录操作......
  • day10:字典的循环遍历及序列操作
    一、字典的循环遍历1.遍历字典的键dict1={'name':'张三','age':20,'gender':'男'}forkeyindict1.keys():print(key)#name#age#gender2.遍历字典的值dict1={'name':'张三','age':20,'......
  • PHP debug_backtrace() 函数
    定义和用法debug_backtrace()函数生成backtrace。该函数显示由debug_backtrace()函数代码生成的数据。返回一个关联数组。下面是可能返回的元素:名称类型描述functionstring当前的函数名。lineinteger当前的行号。filestring当前的文件名。classstring当......
  • 面经_操作系统
    操作系统线程和进程的区别、应用场景线程(Thread)和进程(Process)是操作系统中管理和执行任务的基本单元,它们有一些重要的区别和应用场景。线程和进程的区别:进程:进程是资源调度的最基本单位。每个进程都有自己的地址空间、内存、数据栈等,是操作系统中的资源分配单位。进程之间......
  • C++重载操作符
    在C++中,重载操作符<和重载函数调用操作符()各自适用于不同的情况,它们的使用取决于你的具体需求。比较<和()重载操作符<排序和比较:当你需要定义一个类或结构体的对象如何进行排序或比较时,你会重载操作符<。这在使用标准库中的排序函数(如std::sort)、集合(如std::set......
  • C语言文件操作
    前言我们先假设想一下如果没有文件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失了,等再次运行程序,是看不到上次程序的数据的,如果要将数据进行持久化的保存,我们可以使用文件,本篇就来探讨一下C语言有关文件的操作。个人主页:小张同学zkf若有问题 ......