04-文件

文件读写回顾

// 1、字符的读写回顾 fgetc(), fputc()
void test01()
{
	// 写文件
	FILE *f_write = fopen("./test1.txt", "w");
	if (f_write == NULL)
	{
		return;
	}

	char buf[] = "hello world";
	for (int i = 0; i < strlen(buf); i++)
	{
		fputc(buf[i], f_write);
	}
	fclose(f_write);
	// 读文件
	FILE *f_read = fopen("./test1.txt", "r");
	if (f_read == NULL)
	{
		return;
	}
	char ch;
	char *str = NULL;
	int i = 0;
	str = (char *)malloc(sizeof(char) * 64);
	while ((ch = fgetc(f_read)) != EOF) // EOF  END  OF  FILE
	{
		printf("%c", ch);
		str[i++] = ch;
	}
	printf("%s\n", str);
	fclose(f_read);
}

行读写函数回顾

![[Pasted image 20231008171640.png]]

// 行读写函数回顾
void test02()
{
	// 文件写入
	FILE *fp_write = NULL;
	fp_write = fopen("./mydata.txt", "w+");
	if (fp_write == NULL) {
		perror("open file");
	}

	char *buf[] = {
		"01 this is a test for pfutc!\n",
		"02 this is a test for pfutc!\n",
		"03 this is a test for pfutc!\n", 
		"04 this is a test for pfutc!\n",
	};

	for (int i = 0; i < 4; i++) {
		fputs(buf[i], fp_write);
	} 
	fclose(fp_write);

	// 文件读取
	FILE *fp_read = NULL;
	fp_read = fopen("./mydata.txt", "r");
	if (fp_read == NULL) {
		perror("read fail");
	}

	// 判断文件末尾
	while (!feof(fp_read))
	{
		char temp[1024] = {0};
		fgets(temp, sizeof(temp), fp_read);
		printf("%s", temp);
	}
	fclose(fp_read);
}

块读写回顾

![[Pasted image 20231008173914.png]]

// 块读写函数回顾
typedef struct _TEACHER {
	char name[64];
	int age;
}Teacher;
void test03()
{
	// 写文件
	FILE *fp_write = NULL;
	// 写方式打开文件
	fp_write = fopen("./mydata2.txt", "wb");
	if (fp_write == NULL) {
		perror("write open fail");
	}
	Teacher teachers[4] = {
		{ "Obama2", 33 },
		{ "John2", 28 },
		{ "Edward2", 45},
		{ "Smith2", 35}
	};

	// for (int i = 0; i < 4; i++) {
	// 	fwrite(&teachers[i], sizeof(Teacher), 1, fp_write);
	// }
	fwrite(&teachers, sizeof(Teacher), 4, fp_write);
	
	// 关闭文件
	fclose(fp_write);

	// 读文件
	FILE *fp_read = NULL;
	fp_read = fopen("./mydata2.txt", "rb");
	if (fp_read == NULL) {
		perror("read fail");
	}
	Teacher temps[4];
	fread(&temps, sizeof(Teacher), 4, fp_read);
	for (int i = 0; i < 4; i++) {
		printf("name : %s, age : %d\n", temps[i].name, temps[i].age);
	}
	fclose(fp_read);
}

格式化读写函数回顾

注意fscanf遇到空格和换行时结束

// 格式化读写函数回顾
void test04()
{
	// 写文件
	FILE *fp_write = NULL;
	// 写文件打开方式
	fp_write = fopen("./mydata3.txt", "w");
	if (fp_write == NULL) {
		perror("file write open fail");
	}

	fprintf(fp_write, "hello world->%d!", 20);
	// 关闭文件
	fclose(fp_write);

	// 读文件
	FILE *fp_read = NULL;
	fp_read = fopen("./mydata3.txt", "rb");
	if (fp_read == NULL) {
		perror("file read open fail");
	}
	
	char temp[1024] = {0};
	while (!feof(fp_read))
	{
		fscanf(fp_read, "%s", temp);
		printf("%s", temp);
	}
	fclose(fp_read);
}

随机读写函数回顾

![[Pasted image 20231008214913.png]]

void test05(){
	//写文件
	FILE* fp_write = NULL;
	//写方式打开文件
	fp_write = fopen("./mydata.txt", "wb");
	if (fp_write == NULL){
		perror("fopen:");
		return;
	}

	Teacher teachers[4] = {
		{ "Obama", 33 },
		{ "John", 28 },
		{ "Edward", 45 },
		{ "Smith", 35 }
	};

	for (int i = 0; i < 4; i++){
		fwrite(&teachers[i], sizeof(Teacher), 1, fp_write);
	}
	//关闭文件
	fclose(fp_write);

	//读文件
	FILE* fp_read = NULL;
	fp_read = fopen("./mydata.txt", "rb");
	if (fp_read == NULL){
		perror("fopen:");
		return;
	}

	Teacher temp;
	//读取第三个数组
	fseek(fp_read , sizeof(Teacher) * 2 , SEEK_SET);
	fread(&temp, sizeof(Teacher), 1, fp_read);
	printf("Name:%s Age:%d\n",temp.name,temp.age);
	// 这里先打印的"Edward", 45

	memset(&temp,0,sizeof(Teacher));

	// sizeof的返回值是一个unsigned int
	fseek(fp_read, -(int)sizeof(Teacher), SEEK_END);
	fread(&temp, sizeof(Teacher), 1, fp_read);
	printf("Name:%s Age:%d\n", temp.name, temp.age);

	// 将文件指针重置到文件的开头
	rewind(fp_read);
	fread(&temp, sizeof(Teacher), 1, fp_read);
	printf("Name:%s Age:%d\n", temp.name, temp.age);

	fclose(fp_read);
}

配置文件读写案例

![[Pasted image 20231009140610.png]]

main.c

#include<stdio.h>  
#include<string.h>  
#include<stdlib.h>  
#include "config.h"  
struct Person  
{  
    char a;  
    int b;  
};  
  
void test01()  
{  
    char * filePath = "D:\\project\\code\\01_work_plan\\clion\\untitled\\config.txt";  
  
    int line = getFileLine(filePath);  
//  
    printf("valid file nums is : %d\n", line);  
  
    struct ConfigInfo * pArray = NULL;  
  
    parseFile(filePath, line, &pArray);  
  
    //测试 根据key 访问value  
    printf("heroId = %s\n", getInfoByKey("heroId", pArray, line));  
    printf("heroName = %s\n", getInfoByKey("heroName", pArray, line));  
    printf("heroAtk = %s\n", getInfoByKey("heroAtk", pArray, line));  
    printf("heroDef = %s\n", getInfoByKey("heroDef", pArray, line));  
    printf("heroInfo = %s\n", getInfoByKey("heroInfo", pArray, line));  
  
  
    //释放内存  
    freeSpace(pArray);  
    pArray = NULL;  
}  
  
int main(){  
  
    test01();  
  
    system("pause");  
    return EXIT_SUCCESS;  
}

config.h

#pragma  once  
#define _CRT_SECURE_NO_WARNINGS  
#include<stdio.h>  
#include<string.h>  
#include<stdlib.h>  
  
struct ConfigInfo  
{  
    char key[64]; //索引值  
    char value[64]; //实值  
};  
  
  
//获取有效行数  
int getFileLine(const char * fileName);  
  
//判断当前行是否有效  
int isValidLine(const char * str);  
  
  
//解析文件  
void parseFile(char * filePath, int lines, struct ConfigInfo **  configInfo);  
  
//根据索引值 获取 实值  
char * getInfoByKey(char * key, struct ConfigInfo * configInfo, int line);  
  
//释放信息  
void freeSpace(struct ConfigInfo * configInfo);

config.c

#include "config.h"  
  
//获取有效行数  
int getFileLine(const char * fileName)  
{  
    FILE * file = fopen(fileName, "r");  
//    如果读取失败  
    if (file == NULL)  
    {  
        perror("file open fail");  
        return -1 ;  
    }  
  
    char buf[1024] = { 0 };  
    int lines = 0;  
    while (fgets(buf, 1024, file) != NULL)  
    {  
        //如果是有效行 才统计  
        if (isValidLine(buf))  
        {  
            lines++;  
        }  
  
    }  
    fclose(file);  
  
    return lines;  
}  
  
//判断当前行是否有效  
int isValidLine(const char * str)  
{  
//  strchr,检测字符  
//  函数返回指向第一个匹配字符的指针,如果未找到匹配字符,则返回NULL。  
    if (str[0] == ' ' || str[0] == '\0' ||  strchr(str,':') == NULL)  
    {  
        return 0; //无效数据 都返回假  
    }  
    return 1;  
}  
  
  
//解析文件  
void parseFile(char * filePath, int lines, struct ConfigInfo **  configInfo)  
{  
//    首先分配内存  
//  这是一个结构体数组指针  
    struct ConfigInfo  * info =  malloc(sizeof(struct ConfigInfo) * lines);  
  
    if (info == NULL)  
    {  
        return;  
    }  
  
    FILE * file = fopen(filePath, "r");  
  
    char buf[1024] = { 0 };  
    int index = 0;  
    while ( fgets(buf,1024,file ) != NULL)  
    {  
        //解析数据  有效数据才解析  
        // heroName:aaaa\n  
        if (isValidLine(buf))  
        {  
            memset(info[index].key, 0, 64);  
            memset(info[index].value, 0, 64);  

// 这里也可以用sscanf的方法,更为简洁
//          %[^a] 匹配非a的任意字符,贪婪性,遇到:停止  
//            sscanf(buf,"%[^:]:%s",info[index].key, info[index].value);
  
            char * pos = strchr(buf, ':'); //pos代表冒号所在位置  
//          pos是冒号的地址,buf是首元素地址1  
            strncpy(info[index].key, buf, pos - buf); //将key截取到 结构体中 最后-1的原因是不需要截取换行符  
//          -1:还需要减去换行符  
            strncpy(info[index].value, pos + 1, strlen(pos + 1) - 1);  
  
//            printf("key =  %s  ", info[index].key);  
//            printf("value =  %s\n", info[index].value);  
            index++;  
  
        }  
  
        memset(buf, 0, 1024);  
  
    }  
  
//    struct ConfigInfo ** configInfo;  
//    configInfo = &pArray;  
//  右边是一级指针,左边对二级指针解引用(对&pArray解引用,就是pArray)之后得到一级指针的地址  
    *configInfo = info;  
}  
  
  
//根据索引值 获取 实值 char * getInfoByKey(char * key, struct ConfigInfo * configInfo, int line)  
{  
    for (int i = 0; i < line;i++)  
    {  
//      这里要用字符串对比函数  
//      根据key找value  
        if ( strcmp (key, configInfo[i].key  ) == 0)  
        {  
            return configInfo[i].value;  
        }  
    }  
    return NULL;  
}  
  
  
//释放信息  
void freeSpace(struct ConfigInfo * configInfo)  
{  
    if (configInfo != NULL)  
    {  
        free(configInfo);  
        configInfo = NULL;  
    }  
  
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值