c语言文件操作的实现

本文详细介绍了C语言中的文件操作,包括基本原理、文件种类(文本文件、二进制文件、数据库文件等)、操作模式(r、w、a等)以及各种函数的使用方法,如fopen、fclose、fgetc、fputc、fread、fwrite和fseek。通过实例演示了如何以不同模式读写文件、格式化读写以及文件复制和格式化字符串处理。
摘要由CSDN通过智能技术生成

c语言文件操作知识及实现

文件操作的基本原理

文件种类

在了解文件操作之前,我们应当理解什么是文件?

文件可以被分为多个种类:

  1. 文本文件(Text file):以字符文本的形式存储数据,通常是人类可读的。文本文件可以包含普通文本、配置文件、源代码等内容。
  2. 二进制文件(Binary file):以二进制形式存储数据,不直接可读。二进制文件可以包含图像、音频、视频、可执行程序等内容。
  3. 数据库文件(Database file):存储结构化数据的文件,可以使用数据库管理系统(如MySQLOracle等)进行读取和操作。数据库文件常用于存储大量结构化数据,如表格数据、记录等。
  4. 压缩文件(Compressed file):通过压缩算法将一个或多个文件压缩为较小的文件。常见的压缩文件格式包括ZIPRARGZIP等,可以节省存储空间和传输时间。
    1. 图像文件(Image file):存储图像数据的文件,如JPEGPNGGIF等格式。图像文件可以包含静态图像、照片、绘图等。
  5. 音频文件(Audio file):存储音频数据的文件,如MP3WAVAAC等格式。音频文件可以包含音乐、语音、声效等。
  6. 视频文件(Video file):存储视频数据的文件,如MP4AVIMOV等格式。视频文件可以包含电影、电视节目、动画等。

不同类型的文件具有不同的数据结构和存储方式,因此需要使用相应的程序或工具来读取和处理对应的文件类型。

文件类型

以上的文件种类,由可以按大类被分为程序文件数据文件,程序文件可以对数据文件进行操作

而根据数据的形式,数据文件又可被分为文本文件以及二进制文件

数据原始在内存中存放是以二进制的形式存储的,如果不加转换就输出到外存,那么你看到的就是一个二进制的文件。换而言之,文本文件是我们能够看懂的内容,而二进制文件是给机器看得懂的内容。

文本文件与二进制文件的关系:文本文件就是通过二进制文件进行通过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");
}

sscanfsprintf

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。最后将指针重新定位至文件开头,遍历输出文件中所有整数数值。


总结

文件的相关操作函数大概是讲完了,个人觉得对于文件操作来说,总而言之,就是应当多上手使用,就可以对其有着更深的理解,用起来也会更加方便。

希望这篇文章能够给你带来帮助!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值