文件读写回顾
// 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);
}
行读写函数回顾
// 行读写函数回顾
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);
}
块读写回顾
// 块读写函数回顾
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);
}
随机读写函数回顾
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);
}
配置文件读写案例
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;
}
}