文件操作详解篇(初学者必看)

✅博客主页:爆打维c-CSDN博客​​​​​​ 🐾

🔹分享c语言知识及代码 


💠目录

一、文件简介

1. 为什么使用文件?

2. 什么是文件?

3.文件名

4.二进制文件和文本文件

二、文件的使用

文件指针概念:

文件的打开和关闭:

操作实例:

1.写入一个字符

2.写入一个字符串

!注意此处写入的整行数据会覆盖原数据

3.读取一个字符:

4.读取多个字符

5.读取指定长度的数据

6.写入结构体信息

​编辑

7.读取文件信息到结构体变量中

8.二进制写入及读取

对比一组函数:

sscanf:

sprintf:

三、文件的随机读写:

fseek函数:

ftell函数:

rewind函数:

四、文件读取结束的判定

feof函数:

文本文件的判断:

二进制文件的判断:


一、文件简介

1. 为什么使用文件?

如果没有文件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失了,等再次运⾏程序,是看不到上次程序的数据的,如果要将数据进行持久化的保存,我们可以使用文件。

2. 什么是文件?

在程序设计中,⽂件有两种:程序⽂件、数据⽂件(从⽂件功能的⻆度来分类的)。

程序⽂件包括源程序⽂件(后缀为.c),⽬标⽂件(windows环境后缀为.obj),可执行程序(windows 环境后缀为.exe)。

3.文件名

文件名包含3部分:⽂件路径+⽂件名主⼲+⽂件后缀 例如 c:\code\test.txt 为了⽅便起⻅,⽂件标识常被称为⽂件名。

4.二进制文件和文本文件

数据以二进制数存储在文件里就是二进制文件,以ASCII码存储就是文本文件

下面给出一段代码能更直观的看到二者区别

下列代码将10000和2以二进制存储在文件中,若直接打开test.txt则会出现乱码的情况

我们需要将打开方式换成以二进制编辑器打开

                                                    VS上打开⼆进制⽂件的⽅法

可以看到数据确实是以二进制数形式存储到文件中的


二、文件的使用

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

VS2013 编译环境提供的 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;  //文件指针变量

定义pf是⼀个指向FILE类型数据的指针变量。可以使pf指向某个文件的⽂件信息区(是⼀个结构体变 量)。通过该⽂件信息区中的信息就能够访问该⽂件。通过文件指针变量能够间接找到与它关联的文件。

文件的打开和关闭:

//打开文件——fopen

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

//关闭文件——fclose

int fclose ( FILE * stream );

🔹文件的打开模式:

🔹文件的顺序读写

操作实例:

1.写入一个字符

fputc('a', p);

2.写入一个字符串

fputs("abcdefj", p);

!注意此处写入的整行数据会覆盖原数据

3.读取一个字符:

4.读取多个字符

5.读取指定长度的数据

注意 fgets函数的使用,中间的参数num需要给\0 预留一个字节的位置

如果需要读取5个字节的数据则num处应填6

6.写入结构体信息

#include<stdio.h>
struct Stu {
    int age;
    char id[20];
    char name[20];
};
int main(){
    struct Stu s = { 13,"20238221044","张三" };
    FILE* p = fopen("test.txt", "w"); 
    if (p != NULL) {
        fprintf(p, "%d %s %s", s.age, s.id, s.name);
        p = NULL;
    }
    else { 
        perror("fopen");
        return 1;
    }
    return 0;
}

7.读取文件信息到结构体变量中

#include<stdio.h>
struct Stu {
    int age;
    char id[20];
    char name[20];
};
int main(){
    char arr[10] = { 0 };
    FILE* p = fopen("test.txt", "r"); 
    if (p != NULL) {
        struct Stu s = { 0 };
        fscanf(p, "%d %s %s", &s.age, s.id, s.name);
        printf("该学生年龄为:%d 学号为:%s 姓名为:%s", s.age, s.id, s.name);
        fclose(p);
        p = NULL;
    }
    else { 
        perror("fopen");
        return 1;
    }
    return 0;
}

运行结果:

8.二进制写入及读取

二进制写入函数——fwrite

二进制读取函数——fread

感兴趣的同学自己打开编译器试着操作一下会更有收获


对比一组函数:

scanf/ fscanf / sscanf

printf / fprintf / sprintf

看到s是不是就会自然而然的想到于字符串有关呢?事实确实如此

大家注意不要把sscanf、sprintf与文件操作函数弄混淆

sscanf:

  • int sscanf( const char *buffer, const char *format [, argument ] ... );
  • function:将一个字符串转化为格式化数据;
#include<stdio.h>
int main(){
    char str[] = "20010606wy";   //定义一个字符串
    int day = 0;       
    char name[10] = { 0 };
    sscanf(str, "%d %s", &day,name);
    return 0;
}

运行后:

sprintf:

  • int sprintf( char *buffer, const char *format [, argument] ... );

  • 将一个格式化数据转化为字符串;

#include<stdio.h>
int main(){
    char str[20] = { 0 };
    int day = 20010606;
    char name[5] = "wy";
    sprintf(str, "%d %s", day, name);
    return 0;
}

运行后:

三、文件的随机读写:

在C语言中,fseek、ftell和rewind是用于文件定位和文件指针操作的函数。

下面将详细介绍这三个函数,并给出一些示例:

fseek函数:

▪️ 功能:用于设置文件指针位置。

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

▪️ 参数:

stream:指向FILE类型的指针,表示要进行定位的文件流。
可以是SEEK_SET(文件开头)、SEEK_CUR(当前位置)或SEEK_END(文件末尾)。

offset:long int类型的值,表示相对于origin的偏移量。

origin:用于指定偏移量的起始位置,

▪️ 返回值:

0 表示成功,其他值表示失败。

示例:
FILE *file = fopen("example.txt", "r");
fseek(file, 10, SEEK_SET); // 将文件指针设置到文件开头后的第10个字节处

ftell函数:

▪️函数原型:long int ftell(FILE *stream);
▪️功能:用于获取文件指针的当前位置。
▪️参数:stream:指向FILE类型的指针,表示要获取当前位置的文件流。
▪️返回值:long int类型的值,表示当前位置相对于文件开头的偏移量

示例:
FILE *file = fopen("example.txt", "r");
fseek(file, 10, SEEK_SET);
long int position = ftell(file); // 获取文件指针当前位置
printf("Current position: %ld\n", position);

rewind函数:

▪️函数原型:void rewind(FILE *stream);
▪️功能:用于将文件指针重新设置到文件的开头。
▪️参数:stream:指向FILE类型的指针,表示要重新设置位置的文件流。
▪️返回值:无。

示例:
FILE *file = fopen("example.txt", "r");
fseek(file, 10, SEEK_SET);
rewind(file); // 将文件指针重新设置到文件开头

这些函数可以帮助在文件操作过程中进行定位和指针操作。fseek用于设置文件指针位置,ftell用于获取当前位置的偏移量,而rewind用于将文件指针重新设置到文件开头。这些函数在处理文件时非常有用,可以在文件读写过程中进行灵活的定位和操作。


四、文件读取结束的判定

文件读取结束有两种情况:1.读取过程中出现异常 2.读取到文件末尾;

要找出文件读取是哪个原因,就分为以下情况:

1.文本文件是否结束

判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )

• fgetc 判断是否为 EOF .

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

2. 二进制文件是否结束

判断返回值是否⼩于实际要读的个数。

• fread判断返回值是否小于实际要读的个数。

🔹对于读取异常的判断,我们考虑判断 ferror() 函数的返回值:

  1. 若ferrror()为真——异常读取而结束;
  2. 若feof()为真——正常读取到尾而结束;

feof函数:

在C语言中,feof函数用于检查文件流的文件结束标志,用来判断文件读取结束的原因。

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

下面是关于feof函数的详细介绍:

▪️函数原型:int feof(FILE *stream);
▪️功能:用于检查文件流指针所指向的文件是否已经到达文件结尾。
▪️参数:stream为指向FILE类型结构的指针,表示要检查的文件流。
▪️返回值:若到达文件结尾,则返回非零值(1),否则返回零值(0)。

示例:
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
    perror("Error opening file");
    return 1;
}

while (!feof(file)) {
    char ch = fgetc(file);
    if (ch != EOF) {
        printf("%c", ch);
    } else {
        break;
    }
}

fclose(file);

在示例中,首先打开一个文件流,并使用feof函数在循环中检查文件是否已经到达结尾。在循环中,每次读取一个字符,并判断是否为文件结束符EOF,如果不是则输出字符。循环直到文件结束标志被检测到或者文件读取出错时终止。
通过使用feof函数,可以检查文件流是否已经到达结尾,帮助程序在处理文件时进行正确的流程控制。需要注意的是,feof函数只能检查文件流的状态,并不能准确判断文件读取操作的成功与否,因此在实际使用中需要结合其他函数进行合理的错误处理。

文本文件的判断:

#include<stdio.h>
 
int main()
{
	FILE* pf = fopen("test.txt", "r");
 
	if (pf == NULL)
	{
		perror("fopen is failed !");
		return;
	}
	int c = 0;
	//由于要检查EOF——EOF本质是-1——所以是int
	while (c = fgetc(pf) != EOF)
	{
		putchar(c);
	}
	//直到while不执行了—读取结束了—判断是什么原因结束的
	if (ferror(pf))
	{
		printf("读取中出现错误\n");
	}
	else if (feof(pf))
	{
		printf("读取到文件尾\n");
	}
 
	fclose(pf);
	pf = NULL;
 
	return 0;
}

二进制文件的判断:

#include<stdio.h>
 
int main()
{
	FILE* pf = fopen("test.txt", "rb");
	int arr[5] = { 0 };
 
	if (pf == NULL)
	{
		return;
	}
 
	size_t num = fread(arr, sizeof(int), 5, pf);
 
	if (num == 5)
	{
		//说明全部读取成功
		printf("Array read successfully\n");
	}
	else
	{
		//说明读取不够指定长度—判断是什么原因
		if (ferror(pf))
		{
			printf("读取中出现错误\n");
		}
		else if (feof(pf))
		{
			printf("读取到文件尾\n");
		}
	}
 
	fclose(pf);
	pf = NULL;
 
	return 0;
}
  • 31
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值