c语言文件操作知识及实现
文章目录
文件操作的基本原理
文件种类
在了解文件操作之前,我们应当理解什么是文件?
文件可以被分为多个种类:
- 文本文件(Text file):以字符文本的形式存储数据,通常是人类可读的。文本文件可以包含普通文本、配置文件、源代码等内容。
- 二进制文件(Binary file):以二进制形式存储数据,不直接可读。二进制文件可以包含图像、音频、视频、可执行程序等内容。
- 数据库文件(Database file):存储结构化数据的文件,可以使用数据库管理系统(如
MySQL
、Oracle
等)进行读取和操作。数据库文件常用于存储大量结构化数据,如表格数据、记录等。 - 压缩文件(Compressed file):通过压缩算法将一个或多个文件压缩为较小的文件。常见的压缩文件格式包括
ZIP
、RAR
、GZIP
等,可以节省存储空间和传输时间。- 图像文件(Image file):存储图像数据的文件,如
JPEG
、PNG
、GIF
等格式。图像文件可以包含静态图像、照片、绘图等。
- 图像文件(Image file):存储图像数据的文件,如
- 音频文件(Audio file):存储音频数据的文件,如
MP3
、WAV
、AAC
等格式。音频文件可以包含音乐、语音、声效等。 - 视频文件(Video file):存储视频数据的文件,如
MP4
、AVI
、MOV
等格式。视频文件可以包含电影、电视节目、动画等。
不同类型的文件具有不同的数据结构和存储方式,因此需要使用相应的程序或工具来读取和处理对应的文件类型。
文件类型
以上的文件种类,由可以按大类被分为程序文件和数据文件,程序文件可以对数据文件进行操作
而根据数据的形式,数据文件又可被分为文本文件以及二进制文件
数据原始在内存中存放是以二进制的形式存储的,如果不加转换就输出到外存,那么你看到的就是一个二进制的文件。换而言之,文本文件是我们能够看懂的内容,而二进制文件是给机器看得懂的内容。
文本文件与二进制文件的关系:文本文件就是通过二进制文件进行通过ASCII值的转换,以ASCII值中的相对应的字符的形式存储在外存中就叫文本文件
文件的操作模式
在正式学习c语言文件操作的代码前,我们需要先了解c语言文件操作的各种形式以及其字母代表的含义
C语言中文件操作的模式主要由下表所示:
模式 | 含义 |
---|---|
“r” | 读取模式,打开一个文本文件进行读取。文件不存在则打开失败。 |
“w” | 写入模式,打开一个文本文件进行写入。若文件不存在则创建,若存在则清空文件内容。 |
“a” | 追加模式,打开一个文本文件进行追加写入。若文件不存在则创建。 |
“rb” | 二进制读取模式,打开一个二进制文件进行读取。文件不存在则打开失败。 |
“wb” | 二进制写入模式,打开一个二进制文件进行写入。若文件不存在则创建,若存在则清空文件内容。 |
“ab” | 二进制追加模式,打开一个二进制文件进行追加写入。若文件不存在则创建。 |
“r+” | 读写模式,打开一个文本文件进行读写。文件必须存在。 |
“w+” | 读写模式,打开一个文本文件进行读写。若文件不存在则创建,若存在则清空文件内容。 |
“a+” | 读写模式,打开一个文本文件进行追加读写。若文件不存在则创建。 |
“rb+” | 二进制读写模式,打开一个二进制文件进行读写。文件必须存在。 |
“wb+” | 二进制读写模式,打开一个二进制文件进行读写。若文件不存在则创建,若存在则清空文件内容。 |
“ab+” | 二进制追加读写模式,打开一个二进制文件进行追加读写。若文件不存在则创建。 |
其中,以"b"结尾的模式表示二进制方式打开文件。在二进制模式下,文件的数据是以二进制形式进行读写的,而不是以文本形式进行读写。
文件操作代码实现
文件只读方式和读取文件
fgetc
是 file get char 的缩写,意思是从指定的文件中读取一个字符。其用法为:
int fgetc (FILE *fp);
feof
函数用来判断文件内部指针是否指向了文件末尾,它的原型是:
int feof ( FILE * fp );
打开模式:
r
以只读的方式打开,文件必须存在,否则打开失败
#include <stdio.h>
void fileRead() {
FILE* fp = fopen("C:\\Users\\bb\\Desktop\\touch.txt", "r");//设置文件指针
if (fp == NULL) {
perror("open file failed:");//perror会在open file failed:之后打印错误原因
return;
}
while(1)//判断的条件也可以是while(!(feof(fp)))
{
char ch = fgetc(fp);
if(ch == EOF )
{
break;
}
printf("%c", ch);
}
fclose(fp);
}
int main() {
fileRead();
return 0;
}
用只写的方式写入文件
fputc
是 file output char 的缩写,意思是向指定的文件中写入一个字符。fputc
的用法为:
int fputc ( int ch, FILE *fp );
w
:只写模式,如果文件不存在,则创建新文件;如果文件存在,则清空文件内容。
#include <stdio.h>
#include <string.h>
void fileWrite(){
FILE* fp = fopen("C:\\Users\\bb\\Desktop\\touch2.txt", "w");
if (fp == NULL) {
perror("open file failed:");
return;
}
char ch = fputc('B',fp);
printf("%c\n",ch);
char str[]="大家好!";
for(int i=0;i<strlen(str);i++){
ch = fputc(str[i],fp);
printf("%c",ch);
}
fclose(fp);
}
int main() {
fileWrite();
return 0;
}
可读可写的文件操作
w+
:可读可写,如果文件存在则清空文件,不存在时则创建
读写字符串:
fgets
fputs
只会读取一行,需要循环读取才能够读取多行
#include <stdio.h>
#include <string.h>
void fileReadWrite(){
FILE* fp = fopen("C:\\Users\\bb\\Desktop\\touch3.txt", "w+");
char newStr[]={
"12345\n\
67890\n\
一二三四五\n\
五六八九十"
};
if (fp == NULL) {
perror("open file failed:");
return;
}
int data = fputs( newStr,fp);
printf("fputs return : %d\n",data);//成功返回非负值,失败返回EOF
rewind(fp);//将文件指针移动到文件的开头,不移动至开头无法读取
while(!feof(fp))//循环读取多行
{
char buf[128] = {0};
char* str = fgets(buf,sizeof(buf),fp);
printf("%s\n",buf);
}
fclose(fp);
}
int main() {
fileReadWrite();
return 0;
}
清空缓存区语句
while ((ch = getchar()) != EOF && ch != ‘\n’);
格式化读写
读取
1.用fgets
读取
#include <stdio.h>
void fileFormatRead(){
FILE* fp = fopen("C:\\Users\\bb\\Desktop\\information.txt", "r");
if (fp == NULL) {
perror("open file failed:");
return;
}
char buf[4][200] = {0};
fgets(buf[0],sizeof(buf[0]),fp);
puts(buf[0]);
fclose(fp);
}
int main() {
fileFormatRead();
return 0;
}
2.用fscanf
读取
#include <stdio.h>
void fileFormatRead(){
FILE* fp = fopen("C:\\Users\\bb\\Desktop\\information.txt", "r");
if (fp == NULL) {
perror("open file failed:");
return;
}
//读写内容的实现
fclose(fp);
}
int main() {
fileFormatRead();
return 0;
}
不管是什么类型的数据,都已字符串类型进行读取
char buf[4][200] = {0};
fscanf(fp,"%s %s %s %s",buf[0],buf[1],buf[2],buf[3]);
for(int i=0;i<4;i++){
puts(buf[i]);
}
根据不同的数据类型,分别进行读取
char name[20] = { 0 };
char job[20] = { 0 };
float score = 0.0;
int age;
/*验证读入个数是否为4*/
while (fscanf(fp, "%s\t%s\t%f\t%d\n", name, job, &score, &age) == 4){
printf("%s\t%s\t%f\t%d\n", name, job, score, age);//打印数据
}
写入
用fprintf
函数进行写入
#include <stdio.h>
void fileFormatWrite() {
FILE* fp = fopen("C:\\Users\\bb\\Desktop\\information.txt", "w");
if (fp == NULL) {
perror("open file failed:");
return;
}
fprintf(fp, "%s\t%s\t%f\t%d\n", "bb", "学生", 60.0, 18);
fclose(fp);
}
int main() {
fileFormatWrite();
fileFormatRead();
return 0;
}
文件拷贝
//获取文件完整路径中不带后缀名的文件
void getFileName(char* buffer,const char* fileFullPath){
const char* beg = fileFullPath;
const char* end = strrchr(fileFullPath,'.');
//strrchr在fileFullPath读到'.'停止,并返回其最后出现的指针,若未找到则返回空指针
strncpy(buffer,beg+1,end);
puts(buffer);
}
void fileCopy(const char* filename){
FILE* fpr = fopen(filename,"r");//原来的文件
if (fpr == NULL) {
perror("open file failed:");
return;
}
char prefix[100];
getFileName(prefix,const filename);
strcat(prefix,"-副本.txt");
FILE* fpw = fopen(prefix, "w");
if (fpw == NULL) {
perror("open file failed:");
return;
}
while(!feof(fpr)){
char ch = fgetc(fpr);
fputc(ch, fpw);
}
fclose(fpr);
fclose(fpw);
}
int main(){
fileCopy("C:\\Users\\bb\\Desktop\\information.txt");
}
sscanf
和sprintf
sscanf
的用法
功能:
从字符串中按照指定的格式解析数据并赋值给对应的变量。
函数原型:
int sscanf(const char *str, const char *format,...)
参数:
str
:需要解析的字符串
const char *format
:格式字符串,指定了要解析的数据的类型和格式。
...
:可变参数列表,用于接受解析后的数据
代码示例:
#include <stdio.h>
int main() {
char str[] = "John 25";
char name[20];
int age;
sscanf(str, "%s %d", name, &age);
printf("Name: %s\nAge: %d\n", name, age);
return 0;
}
输出结果:
Name: John
Age: 25
sprintf
的用法
功能:将格式化的数据按照指定的格式写入到字符串中。
函数原型:
int sprintf(char *str, const char *format, ...);
-
str
:目标字符串,用于存储格式化后的数据。 -
format
:格式字符串,指定了要格式化的数据的类型和格式。 -
...
:可变参数列表,提供要格式化的数据。
代码示例:
#include <stdio.h>
int main() {
char name[] = "John";
int age = 25;
char str[50];
sprintf(str, "Name: %s\nAge: %d\n", name, age);
printf("%s", str);
return 0;
}
输出结果
Name: John
Age: 25
fread
(二进制输入)
fread
的用法
功能:
从文件中读取二进制数据。
函数原型:
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
参数:
ptr
:存储读取数据的缓冲区。size
:每个数据项的大小,单位是字节。count
:要读取的数据项的个数。stream
:要读取的文件指针。
返回值:实际读到的数据项的个数,如果读取失败或者到达文件结尾,则返回0。
代码示例:
#include <stdio.h>
int main() {
int data[5];
FILE *fp = fopen("C:\\Users\\bb\\Desktop\\information3.txt", "rb");
if (fpr == NULL) {
perror("open file failed:");
return;
}
fread(data, sizeof(int), 5, fp);
fclose(fp);
for (int i = 0; i < 5; i++) {
printf("%d ", data[i]);
}
printf("\n");
return 0;
}
fread
函数从文件中读取20个字节的数据,然后将其解析为5个整数存储到data数组中。
fwrite
(二进制输出)
fread
的用法
功能:
从文件中读取二进制数据。
函数原型:
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);
参数:
ptr
:写入数据的缓冲区。size
:每个数据项的大小,单位是字节。count
:要写入的数据项的个数。stream
:要写入的文件指针。
返回值:实际写入的数据项的个数,如果写入失败或者已经到达文件结尾,则返回0。
代码示例:
#include <stdio.h>
int main() {
int data[5] = {1, 2, 3, 4, 5};
FILE *fp = fopen("data.bin", "wb");
if (fp == NULL) {
printf("Failed to open file.\n");
return 1;
}
fwrite(data, sizeof(int), 5, fp);
fclose(fp);
return 0;
}
将数组内容以二进制形式写入文件,每个整数占用4个字节,因此总共写入20个字节的数据。
以上是fread
函数和fwrite
函数的基本用法。它们可以方便地进行二进制文件的读写操作,并且效率比较高,适用于大规模的数据处理。
fseek
移动文件指针
函数原型:
int fseek(FILE *stream, long offset, int whence);
参数说明:
stream
:文件指针。offset
:偏移量,即要移动的字节数。whence
:起始位置。SEEK_SET
: 文件开头。SEEK_CUR
: 当前位置。SEEK_END
: 文件结尾。
返回值:
- 成功:0
- 失败:非0
#include <stdio.h>
int main() {
FILE *fp = fopen("data.bin", "r+");//假设"data.bin"文件中的内容为:1, 2, 3, 4, 5。
if (fp == NULL) {
printf("Failed to open file.\n");
return 1;
}
// 读取第二个整数并修改为10
fseek(fp, sizeof(int), SEEK_SET);
int data;
fread(&data, sizeof(int), 1, fp);
printf("Previous value: %d\n", data);
data = 10;
fseek(fp, -sizeof(int), SEEK_CUR); // 移动回上一个位置
fwrite(&data, sizeof(int), 1, fp);
fseek(fp, 0, SEEK_SET);// 重新定位文件指针到开头
// 输出文件中的整数值
while (fread(&data, sizeof(int), 1, fp)) {
printf("%d ", data);
}
printf("\n");
fclose(fp);
return 0;
}
输出结果
Previous value: 2
1 10 3 4 5
第一次调用fseek
将位于文件开头的指针指向移动sizeof(int)
个字节,即指向2,用fread
读出第二位2的数值赋给data,并打印出来,此时指针后移一个数据,后将data改为10,再次调用fseek
使得指针往回移动,指向上一个位置,仍为2,运用fwrite
将2改为了10。最后将指针重新定位至文件开头,遍历输出文件中所有整数数值。
总结
文件的相关操作函数大概是讲完了,个人觉得对于文件操作来说,总而言之,就是应当多上手使用,就可以对其有着更深的理解,用起来也会更加方便。
希望这篇文章能够给你带来帮助!
1, fp);
fseek(fp, 0, SEEK_SET);// 重新定位文件指针到开头
// 输出文件中的整数值
while (fread(&data, sizeof(int), 1, fp)) {
printf(“%d “, data);
}
printf(”\n”);
fclose(fp);
return 0;
}
输出结果
```c
Previous value: 2
1 10 3 4 5
第一次调用fseek
将位于文件开头的指针指向移动sizeof(int)
个字节,即指向2,用fread
读出第二位2的数值赋给data,并打印出来,此时指针后移一个数据,后将data改为10,再次调用fseek
使得指针往回移动,指向上一个位置,仍为2,运用fwrite
将2改为了10。最后将指针重新定位至文件开头,遍历输出文件中所有整数数值。
总结
文件的相关操作函数大概是讲完了,个人觉得对于文件操作来说,总而言之,就是应当多上手使用,就可以对其有着更深的理解,用起来也会更加方便。
希望这篇文章能够给你带来帮助!