1.为什么需要文件操作
2.文件的打开与关闭
3.文件指针
4.文件的打开与关闭
5.fopen
6.函数声明
7.文件的打开方式
8.函数使用
9.fclose
10.函数声明
11.函数使用
12.文件的顺序读写
13.fgetc与fputc
14.函数声明
15.函数使用
16.fgets与fputs
17.函数声明
18.函数使用
19.fscanf与fprintf
20.函数声明
21.函数使用
22.fread与fwrite
23.函数声明
24.函数使用
一.fseek函数——
功能:
参数解析:
练习1.要求输出字符c
练习2.要求输出字符f
A.方法1.采用SEEK_CUR 当前指针指向的位置为中心 。
B.方法2:SEEK_CUR 文件指针的当前位置为中心。
C.方法3:SEEK_END 文件结尾为中心。
ftell函数
功能:
rewind函数
功能
代码实践
为什么需要文件操作
文件操作具有以下重要性: 数据永久保存:通过文件操作,我们可以将数据永久保存在硬盘中,即使程序终止或计算机关机,数据仍然可以被保留。 数据共享:通过文件操作,可以将数据保存到文件中,并且可以方便地与其他人共享和传输数据。 数据备份:通过文件操作,可以将重要数据进行备份,以防止数据丢失或损坏。 数据处理:通过文件操作,可以读取文件中的数据并进行处理和分析,从而实现对大批量数据的高效处理和计算。
文件的打开与关闭
fopen:是文件打开库函数
FILE*fopen(const char*filename,const char*mode)
fopen在头文件stdio.h中声明
第一个参数类型是const char*。表示要打开的文件标识。
第二个参数类型是const char*。表示打开文件的方式。
返回值类型是FILE*。打开成功时返回这个文件打开后在内存中的文件信息区结构体的地址;打开失败时返会NULL。
参数(打开方式) 含义
"r" 为输入数据,打开一个已经存在的文本文件
"w" 为了输出数据,新建一个文本文件
"a" 向文本文件的末尾添加数据
"rb" 为了输入数据,打开一个二进制文件
"wb" 为了输出数据,新建一个二进制文件
"ab" 向一个二进制文件的末尾添加数据
"r+" 为了读写,打开一个文本文件
"w+" 为了读写,新建一个文本文件
"a+" 打开一个文本文件,在文件的末尾进行读写
"rb+" 为了读写,打开一个二进制文件
"wb+" 为了读写,新建一个二进制文件
"ab+" 打开一个二进制文件,在文件末尾读写
首先要说明的是,这里的输入数据是指从文件向内存中输入数据,就是读取数据;输出就是从内存向文件中输出数据,就是写入数据。
int main()
{
FILE* p = fopen("text.txt", "r");
if (p == NULL)
{
perror("fopen");
return 1;
}
return 0;
}
这段代码中,fopen的第一个参数是"text.txt";第二个参数是"r"。表示在当前目录中以只读的方式打开test.txt文件。if判断,当返回值为NULL时,即打开失败。此时,我们可以使用库函数perror来打印出错的原因。这个库函数的参数可以作为标识。由于没有在这个目录中创建test的文本文件,所以打印出的错误是:没有这样的文件或目录。
fclose
在打开文件后自然需要关闭文件。我们可以使用库函数fclose。
int fclose(FILE*stream)
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
FILE* p = fopen("text.txt", "r");
if (p == NULL)
{
perror("fopen");
return 1;
}
fclose(p);
p = NULL;
return 0;
}
现在,我已经创建好了一个test.txt文件了,所以能够成功打开。
但是这段代码并没有对这个文件进行读写,所以这个文件中还是空的
文件的顺序读写
刚才的库函数只是打开了某个文件。接下来介绍的这些函数,就可以实现在文件的顺序读写:
fgetc与fputc
fgetc是字符输入函数,适用于所有输入流;fputc是字符输出函数,适用于所有输出流。
fgets有一个参数,类型为FILE*。表示从FILE*指定的流中读取指示符当前的字符到内存中(即将字符输入到内存中)。读取后,标识符向前移动一个字符(这里的标识符可以理解为光标)。返回值类型是int。如果读取成功,返回这个字符的ASCII码值;读取失败,返回EOF。
fputc有两个参数:
第一个参数的类型是int。表示要输出的字符的ASCII码值;
第二个参数的类型是FILE*。表示要将这个字符输出到FILE*指定的流中。
输出后,标识符向前移动一个字符。返回值类型为int。如果输出成功,返回这个字符的ASCII码值;输出失败,返回EOF。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
FILE* p = fopen("text.txt", "w");
if (p == NULL)
{
perror("fopen");
return 1;
}
fputc('a', p);
fclose(p);
p = NULL;
return 0;
}
这段代码使用了"w"输出的方式在当前目录中打开了一个text.txt文件,然后判断是否打开成功,使用fputc函数在这个文本文件中写入字符a。最后关闭文件。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
FILE* p = fopen("text.txt", "r");
if (p == NULL)
{
perror("fopen");
return 1;
}
/*fputc('a', p);*/
int a=fgetc(p);
printf("%c", a);
fclose(p);
p = NULL;
return 0;
}
使用只读"r"的方式打开当前目录中的text.txt文件,并判断是否打开成功,文件中的字符字符依次存储到int型的变量a中并打印。最后关闭文件。
fgets与fputs
fgets是文本行输入函数,适用于所有输入流;fputs是文本行输出函数,适用于所有输出流。
fgets有三个参数:
第一个参数类型为char*。表示将指定流中的字符串输入到的空间的首地址;
第二个参数类型为int。表示读取的字符的个数;
第三个参数类型为FILE*。表示从FILE*指定的流中读取指示符当前的num个字符到str指向的空间中(即将字符串输入到内存中)。读取后,标识符向前移动num个字符。
fputs有两个参数:
第一个参数类型为const char*。表示要输出到指定流的字符串;
第二个参数类型为FILE*。表示将str指向的字符串中的内容输出到FILE*指定的流中。输入后,标识符向后移动到字符串的末尾。
需要注意的是,fputs输出字符串的结束标志是’\0’,并且在输出字符串时不输出’\0’。返回值类型为int。输出成功时返回一个非负值;输出失败时,返回EOF。
函数使用
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
FILE* p = fopen("text.txt", "w");
if (p == NULL)
{
perror("fopen");
return 1;
}
fputs("I am a student", p);
fclose(p);
p = NULL;
return 0;
}
在这段代码中:
首先以"w"的方式在当前目录中打开text.txt文件,并判断是否打开成功("w"的方式打开文件实际上是创建一个新的文件)。再讲字符串使用fputs输入到text.txt中。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
FILE* p = fopen("text.txt", "r");
if (p == NULL)
{
perror("fopen");
return 1;
}
char arr[20] = { 0 };
int a=fgets(arr, 5, p);
printf("%s", a);
fclose(p);
p = NULL;
return 0;
}
需要注意的是,创建的用于存储字符串的数组大小不能小于一次读取的量,否则就会出现数组越界的问题。
fscanf与fprintf
fscanf是格式化输入函数,适用于所有输入流;fprintf是格式化输出函数,适用于所有输出流。
其实这两个函数可以与我们熟知的scanf与printf函数结合理解:
scanf是从标准输入流输入格式化的数据到内存;printf是将格式化的数据以标准输出流的方式输出。
而fscanf可以将所有输入流的数据格式化的输入到内存;fprintf可以将内存中的数据格式化的输出到任何输出流。
标准输入流就是键盘,标准输出流就是屏幕。而我们今天所介绍的文件也是一种流。只不过标准输入流与标准输出流在程序运行的时候系统会自动打开,而其他的流需要我们自己打开。例如我们通过fopen打开一个文件流。
格式化就是整型的格式、浮点型的格式、字符的格式、字符串的格式等。我们用"%d"输出就是按照有符号的十进制整型输出;用"%c"输出就是按照字符输出;用"%s"输出就是按照字符串输出。
函数声明
这两个函数在声明在头文件stdio.h中:
函数使用
在使用时,也是与scanf、printf类似,只是前面需要指定流。
例如将数据格式化的输出到文件流:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
FILE* p = fopen("text.txt", "w");
if (p == NULL)
{
perror("fopen");
return 1;
}
fprintf(p, "%s", "abcde");
fclose(p);
p = NULL;
return 0;
}
将文件流中的数据格式化的输入到内存中:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
FILE* p = fopen("text.txt", "r");
if (p == NULL)
{
perror("fopen");
return 1;
}
/*fprintf(p, "%s", "abcde");*/
char arr[10] = { 0 };
fscanf(p, "%s", arr);
printf("%s ", arr);
fclose(p);
p = NULL;
return 0;
}
fread与fwrite
fread是二进制输入函数,只适用于文件流;fwrite是二进制输出函数,只适用于文件流。
函数声明
这两个函数在声明在头文件stdio.h中
fwrite
fwrite有4个参数:
第一个参数类型为void*。表示将这个ptr指针指向的空间中的元素写入文件(void*可以接收任意类型的指针变量);
第二个参数类型为size_t(无符号整型)。表示输出的每个元素的大小;
第三个参数类型为size_t。表示输出count个大小为size的元素;
第四个参数类型为FILE*。表示将数据输出到指定的FILE*文件流中。
返回值为size_t。返回成功写入的元素总数。
如果此数字与 count 参数不同,则写入错误阻止函数完成。
如果大小或计数为零,则该函数返回零。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
FILE* p = fopen("text.txt", "wb");
if (p == NULL)
{
perror("fopen");
return 1;
}
int arr[20] = { 1,2,3,4,5,6,7,8,9,10 };
for (int i = 0; i < 10; i++)
{
fwrite(arr+i, sizeof(int), 1, p);
}
fclose(p);
p = NULL;
return 0;
}
由于fwrite是用于在二进制文件中写入数据,所以在打开文件时需要使用"wb"的方式。
并且在使用记事本打开时是无法读取的,所以是乱码。
当我们再使用二进制的方式读取时,即可获得其数据:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
FILE* p = fopen("text.txt", "rb");
if (p == NULL)
{
perror("fopen");
return 1;
}
/*int arr[20] = { 1,2,3,4,5,6,7,8,9,10 };
for (int i = 0; i < 10; i++)
{
fwrite(arr+i, sizeof(int), 1, p);
}*/
int n = 0;
for (int i = 0; i < 10; i++)
{
int a = fread(&n, sizeof(int), 1, p);
printf("%d ", n);
}
fclose(p);
p = NULL;
return 0;
在这篇文章中我们了解了文件的打开与关闭、文件的顺序读写的相关函数。
其实有一些内容是没有介绍到的。比如当读写结束后原因的判断,到底是因为读写到了末尾,还是读写错误;比如二进制文件与文本文件;比如文件的随机读写等一些相关内容。
fseek函数
1. 功能:
根据文件指针的位置和偏移量来定位文件指针。(只用来:定位!!!
2.参数解析:
fseek第一个参数为流,第二个参数为偏移量,第三个参数为文件指针定位的位置
SEEK_SET 以文件开头为中心
SEEK_CUR 文件指针的当前位置为中心
SEEK_END 文件结尾为中心
不适用fseek:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
FILE* p = fopen("text.txt", "r");
if (p == NULL)
{
perror("fopen");
return 1;
}
int a = 0;
a = fgetc(p);
printf("%c\n", a);
a = fgetc(p);
printf("%c\n", a);
a = fgetc(p);
printf("%c\n", a);
fclose(p);
p = NULL;
return 0;
}
代码讲解:字符输出函数——fgetc(),一次读取一个字符。使用fgetc函数时,第一次指针只能指向开头位置,每使用一次fgetc才能读取一个字符,指针会逐步向后,这种方法很死板,不能随心所欲的想指向哪个文件内容就指向哪个。
使用fseek:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
FILE* p = fopen("text.txt", "r");
if (p == NULL)
{
perror("fopen");
return 1;
}/*
int a = 0;*/
/* a = fgetc(p);
printf("%c\n", a);
a = fgetc(p);
printf("%c\n", a);
a = fgetc(p);
printf("%c\n", a)*/;
fseek(p, 2, SEEK_SET);
int a=fgetc(p);
printf("%c ", a);
fclose(p);
p = NULL;
return 0;
}
代码讲解: fseek(pf, 2, SEEK_SET);
这句代码意为:将文件指针指向文件内容开头位置,偏移量为2,偏移量0代表a,2代表0+2,即文件指针指向a之后的第2个字符c。
二.ftell函数
long int ftell ( FILE * stream );
1.功能:
返回文件指针相对于起始位置的偏移量。
ftell的使用:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
FILE* p = fopen("text.txt", "r");
if (p == NULL)
{
perror("fopen");
return 1;
}/*
int a = 0;*/
/* a = fgetc(p);
printf("%c\n", a);
a = fgetc(p);
printf("%c\n", a);
a = fgetc(p);
printf("%c\n", a)*/;
fseek(p, 2, SEEK_SET);
int a=fgetc(p);
printf("%c\n", a);
printf("%d\n", ftell(p));
fseek(p, -2, SEEK_END);
int b = fgetc(p);
printf("%c\n", b);
printf("%d\n", ftell(p));
fclose(p);
p = NULL;
return 0;
}
三.rewind函数
1.功能:
让文件指针的位置回到文件的起始位置。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
FILE* p = fopen("text.txt", "r");
if (p == NULL)
{
perror("fopen");
return 1;
}/*
int a = 0;*/
/* a = fgetc(p);
printf("%c\n", a);
a = fgetc(p);
printf("%c\n", a);
a = fgetc(p);
printf("%c\n", a)*/;
fseek(p, 2, SEEK_SET);
int a=fgetc(p);
printf("%c\n", a);
printf("%d\n", ftell(p));
rewind(p);
printf("%d\n", ftell(p));
fseek(p, -2, SEEK_END);
int b = fgetc(p);
printf("%c\n", b);
printf("%d\n", ftell(p));
rewind(p);
printf("%d\n", ftell(p));
fclose(p);
p = NULL;
return 0;
}