【C 语言】文件操作 ( 配置文件读写 | 完整代码示例 ) ★
生活随笔
收集整理的這篇文章主要介紹了
【C 语言】文件操作 ( 配置文件读写 | 完整代码示例 ) ★
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 一、頭文件 cfg.h
- 二、核心業務 cfg.c
- 三、主函數
- 四、執行結果
一、頭文件 cfg.h
// 防止多次導入 #ifndef __CFG_H__ #define __CFG_H__// 兼容 C++ #ifdef __cplusplus extern "C" { #endif // __cplusplus// 定義接口時 , 如果函數形參用作輸入數據時 , 可以在形參名很后面添加 /*in*/ 注釋 //// 獲取配置項 int read_config_file(char *filename /*in*/, char *key /*in*/, char * value/*in out*/, int * value_len /*out*/);// 寫出 / 更新配置項 int write_or_update_config_file(char *filename /*in*/, char *key /*in*/, char *value/*in*/, int value_len /*in*/);#ifdef __cplusplus } #endif // __cplusplus#endif // __CFG_H__
二、核心業務 cfg.c
#define _CRT_SECURE_NO_WARNINGS #include <stdlib.h> #include <string.h> #include <stdio.h>// 每行最長的大小 #define MAX_LINE 256/*** @brief read_config_file 讀取配置文件* @param filename 文件名* @param key 鍵* @param value 值* @param value_len 值字符串長度* @return*/ int read_config_file(char *filename /*in*/, char *key /*in*/, char *value/*in out*/, int *value_len /*out*/) {// 返回值int ret = 0;// 文件指針FILE *fp = NULL;// 靈活使用的臨時指針char *p = NULL;// 指向 Value 開始位置的指針char *start = NULL;// 指向 Value 結束位置的指針char *end = NULL;// 存儲配置文件中的一行數據char line_buffer[MAX_LINE];// 以只讀的方式打開文件fp = fopen(filename, "r");// 如果文件打開失敗 , 說明文件不存在 , 直接退出if (fp == NULL){ret = -1;return ret;}// 逐行遍歷 配置文件 中的文本數據while (!feof(fp)){// 清空 line_buffer 中的遺留數據 , 避免被上一次寫入的數據干擾memset(line_buffer, 0, sizeof(line_buffer));// 獲取一行數據fgets(line_buffer, MAX_LINE, fp);// 查找 '=' 字符p = strchr(line_buffer, '=');// 如果沒有找到 '=' 字符 , 則退出 , 繼續執行下一次循環if (p == NULL){continue;}// 查找 Key 值// 如果找到了 Key 關鍵字 , 則返回的指針 p 指向 Key 關鍵字出現的首地址中p = strstr(line_buffer, key);// 如果沒有找到 Key 關鍵字 , 退出執行下一次循環換if (p == NULL){continue;}// 越過 Key 關鍵字 , 從 Key 關鍵字后面的內容遍歷p = p + strlen(key);// 查找 '=' 字符p = strchr(p, '=');// 如果沒有找到 '=' 字符 , 則退出 , 繼續執行下一次循環if (p == NULL){continue;}// 越過 '=' 字符 , 從 '=' 字符 后面的內容遍歷p = p + 1;// 獲取 Value 起始位置for(;;){// 去掉開始位置的空格if (*p == ' '){p ++ ;}else{start = p;if (*start == '\n'){// 進入到該分支 , 說明 Value 值是空的// 直接退出即可goto End;}break;}}// 獲取 Value 結束位置// 從 Value 的不為空格的位置開始遍歷for(;;){// 遇到空格或回車 , 說明讀取到了最后的位置, 或者換行位置if ((*p == ' ' || *p == '\n')){break;}else{p ++;}}end = p;// 通過 間接賦值 設置 Value 值長度*value_len = end - start;// 通過 間接賦值 設置 Value 值數據內容memcpy(value, start, end - start);}End:// 關閉文件if (fp == NULL){fclose(fp);}return 0;}/*** @brief write_or_update_config_file 寫出或更新配置項* 遍歷每行數據 , 檢查 key 鍵 是否存在* 如果存在 , 就更新對應的 value 值* 如果不存在 , 在文件末尾添加該鍵值對信息* 格式為 :* key = value** @param filename 文件名稱* @param key 鍵* @param value 值* @param value_len 值的長度* @return*/ int write_or_update_config_file(char *filename /*in*/, char *key /*in*/, char * value/*in*/, int value_len /*in*/) {// 返回值int ret = 0;// 查詢配置文件中 Key 是否存在int key_exist = 0;// 統計的配置文件大小int file_length = 0;// 文件指針FILE *fp = NULL;// 存儲讀取的每一行配置文件信息char line_buffer[MAX_LINE];// 臨時指針char *p = NULL;// 文件數據緩存區char file_buffer[1024 * 4] = {0};// 驗證指針有效性if (filename == NULL || key == NULL || value == NULL){ret = -1;printf("error : filename == NULL || key == NULL || value == NULL \n");goto End;}// 使用讀寫方式打開 filename 文件fp = fopen(filename, "r+");// 如果打開失敗 提示失敗信息if (fp == NULL){ret = -2;printf("error : fopen \n");}// 如果文件打開失敗 , 說明沒有文件if (fp == NULL){// 以寫的方式 , 打開文本文件 , 如果文件不存在 , 則創建文件fp = fopen(filename, "w+t");// 打開失敗 , 直接退出if (fp == NULL){ret = -3;printf("error : fopen \n");goto End;}}// 統計文件大小// 將文件指針移動到末尾fseek(fp, 0L, SEEK_END);// 獲取當前指針位置 , 當前指針位置就是文件大小file_length = ftell(fp);// 將文件指針指向開始位置fseek(fp, 0L, SEEK_SET);// 文件大小不能超過 4Kif (file_length > 1024 * 4){ret = -3;printf("File Size More Than 4K\n");goto End;}// 逐行遍歷配置文件while (!feof(fp)){// 將 line_buffer 數據清空memset(line_buffer, 0, sizeof(line_buffer));// 獲取 fp 文件的一行數據 , 保存到 line_buffer 數組中 , 最多獲取 MAX_LINE 字節p = fgets(line_buffer, MAX_LINE, fp);// 如果獲取失敗 , 則返回 NULL// 獲取成功 , 返回的是 line_buffer 地址if (p == NULL){break;}// 查詢 本行字符數組中是否包含 鍵 Keyp = strstr(line_buffer, key);// 本行不包含 Key , 將數據行 line_buffer// 追加拷貝到 file_buffer 數組中if (p == NULL){strcat(file_buffer, line_buffer);continue;}else{// 如果 Key 關鍵字 在本行 , 則使用新的數據替換原來的數據 , 最后拷貝到 file_buffer 中// 替換本行數據sprintf(line_buffer, "%s = %s\n", key, value);// 將替換的數據 , 追加拷貝到 file_buffer 數組中strcat(file_buffer, line_buffer);// 設置 Key 存在標志位key_exist = 1;}}// 如果 Key 關鍵字不存在 , 直接將數據追加到文件末尾即可if (key_exist == 0){fprintf(fp, "%s = %s\n", key, value);}else // 如果 Key 關鍵字存在 , 則需要重新寫出該文件的數據 , 原來的數據直接刪除覆蓋{// 先關閉之前的 文件指針if (fp != NULL){fclose(fp);fp = NULL;}// 重新打開文件fp = fopen(filename, "w+t");if (fp == NULL){ret = -4;printf("fopen() err. \n");goto End;}// 將文件的完整數據 , 寫出到 fp 中// 注意此處的文件數據 , 沒有原來的 鍵值對數據// 寫入了要更新的鍵值對數據fputs(file_buffer, fp);// 也可以使用 fwrite 函數 , 向文件中寫出數據//fwrite(filebuf, sizeof(char), strlen(filebuf), fp);}End:// 關閉文件if (fp != NULL){fclose(fp);}return ret; }
三、主函數
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "cfg.h"// 配置文件名稱 #define CONFIG_FILE_NAME "D:/File/config.ini"/*** @brief show_menu* 顯示應用操作菜單*/ void show_menu() {printf("=============================\n");printf("1 Write Config File\n");printf("2 Read Config File\n");printf("0 Quit\n");printf("=============================\n"); }/*** @brief read_config* 從配置文件中 , 讀取配置文件 鍵值對 信息* @return*/ int read_config() {// 局部變量 返回值 , 用于表示程序狀態int ret = 0;// 讀取 的配置項// 數組聲明會后 , 注意先進行初始化為 0 操作 , 否則其中的數據可能是隨機的char key[256] = {0}; // Key 鍵char value[256] = {0}; // Value 值// 值 Value 的長度int value_len = 0;// 提示輸入 Key 鍵printf("\nPlease Input Key : ");// 將 Key 存儲到 name 字符串數組中scanf("%s", key);// 從 D:/File/config.ini 讀取 鍵值對 信息ret = read_config_file(CONFIG_FILE_NAME /*in*/, key /*in*/, value/*in*/, &value_len /*out*/);if (ret != 0){printf("error : read_config : %d \n", ret);return ret;}// 打印查詢結果printf("Get Value Success , Value = %s \n", value);}/*** @brief write_update_config* 啟動 寫出 / 更新 配置項 模塊 , 執行 寫出 / 更新 配置項操作* @return*/ int write_update_config() {// 局部變量 返回值 , 用于表示程序狀態int ret = 0;// 寫出 或 更新 的配置項// 數組聲明會后 , 注意先進行初始化為 0 操作 , 否則其中的數據可能是隨機的char key[256] = {0}; // Key 鍵char value[256] = {0}; // Value 值// 提示輸入 Key 鍵printf("\nPlease Input Key : ");// 將 Key 存儲到 name 字符串數組中scanf("%s", key);// 提示輸入 Value 值printf("\nPlease Input Value : ");// 將 Value 值 存儲到 value 字符串數組中scanf("%s", value);// 向 D:/File/config.ini 寫出或更新 鍵值對 信息ret = write_or_update_config_file(CONFIG_FILE_NAME /*in*/, key /*in*/, value/*in*/,strlen(value) /*in*/);// 判定執行中是否出錯if (ret != 0){printf("error : write_or_update_config : %d \n", ret);return ret;}// 打印成功插入的鍵值對printf("Input %s = %s Success !\n", key , value);return ret; }/*** @brief main 主函數入口*/ void main() {// 用戶輸入的選項 , 0 退出 , 1 寫出配置 , 2 讀取配置int user_input;// 啟動無限循環for (;;){//顯示一個菜單show_menu();// 從命令行接收 int 值 , 作為菜單選擇scanf("%d", &user_input);// 根據用戶的不同輸入 , 進行不同的操作switch (user_input){case 1: // 寫出 或 更新配置項write_update_config();break;case 2: // 讀取配置項read_config();break;case 0: // 退出程序exit(0);default: // 無法識別的操作 , 提示錯誤操作 , 繼續printf("Input Error !\n");break;}}// 執行完畢會后暫停system("pause");return ; }
四、執行結果
插入數據 :
查詢數據 :
總結
以上是生活随笔為你收集整理的【C 语言】文件操作 ( 配置文件读写 | 完整代码示例 ) ★的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【C 语言】文件操作 ( 配置文件读写
- 下一篇: 【C 语言】文件操作 ( 文件加密解密