主要就是讀取資料
以及一些將字串分割的函式
而且fileio也可以直接讀取壓縮黨(zip)內的內容
fileio.h
#ifndef __FILEIO_H #define __FILEIO_H #include "defines.h" #if defined(RB_MSVC_WIN32) //#define USE_ZZIP #endif #ifdef USE_ZZIP //定義讀取檔案的格式型態 #include <zzip/zzip.h> typedef ZZIP_FILE FILEIO; typedef zzip_size_t FILEIO_SIZE_T; typedef zzip_off_t FILEIO_OFF_T; #else #include <stdio.h> typedef FILE FILEIO; typedef size_t FILEIO_SIZE_T; typedef long FILEIO_OFF_T; #endif #define INI_MAXLINESIZE (1024) #define INI_MAXELEMSIZE (256) typedef struct { int type; char itemname[INI_MAXELEMSIZE+1]; char itemvalue[INI_MAXELEMSIZE+1]; } INI_ITEM_t; // type : INI_GROUPTITLE , INI_GROUPITEM or UNKNOW. itemname = itemvalue <==> cmd = XXXX.cmd //-- values for INI_ITEM_t.type #define INI_GROUPTITLE (0) #define INI_GROUPITEM (1) #define INI_UNKNOWNITEM (2) #ifdef __cplusplus extern "C" { //讓C++' 將以下內容用C語言讀取 #endif int ini_ReadNextItem(FILEIO* ini_fp, INI_ITEM_t* iniitem); bool ini_IsGroup(INI_ITEM_t* item, const char* title); bool ini_IsItem(INI_ITEM_t* item, const char* name); bool ini_IsNumber(char* str); void ini_InitialItem(INI_ITEM_t* item); char* ini_RemoveSpace(char* str); //may break str's content int ini_ParseNumber_pre(char *str, const char *prefix, int *data); int ini_ParseNumber_post(char *str, const char *postfix, int *data); int ini_DivideString(char *str, char **str1, char **str2, const char *fix); int ini_GetCH(char *str, int *ch); int ini_GetValue(char *str, int *value); FILEIO* ini_FileOpen(char* filename); void ini_FileClose(FILEIO* fp); FILEIO* fileio_FileOpen(char* filename, const char* mode); void fileio_FileClose(FILEIO* fp); FILEIO_SIZE_T fileio_Read(void* buf, FILEIO_SIZE_T size, FILEIO_SIZE_T count, FILEIO* fp); char* fileio_ReadLine(FILEIO* fp, char* buf, int maxcnt); int fileio_GetChar(FILEIO* fp); int fileio_Seek(FILEIO* fp, FILEIO_OFF_T offset, int origin); FILEIO_OFF_T fileio_GetPos(FILEIO* fp); FILEIO_SIZE_T fileio_GetSize(FILEIO* fp); bool fileio_Exist(char* filename); int fileio_IsFileEnd(FILEIO* fp); #ifdef __cplusplus } #endif #endif
fileio.cpp
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include "fileio.h" #include "errcode.h" #if defined(RB_LINUX) #define _stricmp strcasecmp #define _strnicmp strncasecmp #elif defined(RB_BC_DOS) || defined(RB_DJGPP) #define _stricmp stricmp #define _strnicmp strnicmp #endif /*********************** Functions for .ini Files ***************************/ void ini_InitialItem(INI_ITEM_t* item) //預設值 { item->itemname[0] = item->itemvalue[0] = '\0'; item->type = INI_UNKNOWNITEM; } int ini_GetValue(char *str, int *value) //將字串轉為數字 非數字則回傳'無效值' { if(!ini_IsNumber(str)) return INI_INVALID_VALUE; *value = atol(str); return SUCCESS; } static char* ini_RemoveComment(char* str) { //將程式寫法改為電腦讀取方法 即int a; >> "int a\0" if (str != NULL) str[strcspn(str, ";")] = '\0'; //strcspn 尋找字元位置 return str; } int ini_DivideString(char *str, char **str1, char **str2, const char *fix) //分割字串以fix為分割點 { int i; i = (int)strcspn(str, fix); if(str[i] == '\0') return INI_DIVIDE_FAIL; str[i] = '\0'; *str1 = ini_RemoveSpace(str); *str2 = ini_RemoveSpace(&str[i+1]); if(strlen(*str1) == 0) return INI_DIVIDE_STR1; if(strlen(*str2) == 0) return INI_DIVIDE_STR2; return SUCCESS; } char* ini_RemoveSpace(char* str) { //刪除前後的無意義字元 ex: ' ' , '\t' int i; if (str == NULL) return str; i = (int)strlen(str); if (i == 0) return str; else i--; //ignore empty string //remove tail space chars while((i >= 0) && ((str[i] == ' ') || (str[i] == '\t'))) i--; str[i + 1] = '\0'; //remove head space chars i = 0; while ((str[i] == ' ') || (str[i] == '\t')) i++; return &(str[i]); /* //remove all space in the string int i = 0, j = 0; while ((str[i] = str[j++]) != '\0') if (str[i] != ' ') i++; */ } bool ini_IsNumber(char* str) { //判斷是否為正整數 if (*str == '\0') return false; while (*str != '\0') { if ((*str < '0') || (*str > '9')) return false; str++; } return true; } int ini_ParseNumber_pre(char *str, const char *prefix, int *data) //分析字首 { int i; // ini_RemoveSpace(str); i = (int)strlen(prefix); if (str == NULL) return INI_NUMPRE_NULL; //若str為空值 回傳INI_NUMPRE_NULL if((strlen(str) <= (unsigned)i) || (_strnicmp(str, prefix, i) != 0)) return INI_NUMPRE_INVALID; //若prefix字數大於str 或 prefix與str的前 i 個數不同 回傳INI_NUMPRE_INVALID str = ini_RemoveSpace(&str[i]); //刪除前後的無意義字元 ex: ' ' , '\t' if(!ini_IsNumber(str)) return INI_NUMPRE_FAIL; //不為數字回傳INI_NUMPRE_FAIL *data = atol(str); //轉為long return SUCCESS; } int ini_ParseNumber_post(char *str, const char *postfix, int *data) //分析字尾 { int i; char *str2; if(str == NULL) return INI_NUMPOST_NULL; //若str為空值 回INI_NUMPOST_NULL i = (int)strcspn(str, postfix); //尋找字元相同位置 相同的前一個 if(str[i] != '\0'){ //要判斷不為\0 因為\0就已經是結尾了 str2 = ini_RemoveSpace(&str[i]); //刪除前後的無意義字元 ex: ' ' , '\t' if(_stricmp(str2, postfix) != 0) return INI_NUMPRE_INVALID; //判斷字串若不相同回傳INI_NUMPRE_INVALID 不區分大小寫 } str[i] = '\0'; //簡單的說就是保留前 i 個與postfix不同的字 str = ini_RemoveSpace(str); if(!ini_IsNumber(str)) return INI_NUMPRE_FAIL; //刪除前後的無意義字元 ex: ' ' , '\t' *data = atoi(str); //轉換為數字 return SUCCESS; } FILEIO* ini_FileOpen(char* filename) { //呼叫fileio_FileOpen 然後回傳檔案位置 在205行 return fileio_FileOpen(filename, "r"); } void ini_FileClose(FILEIO* fp) { //把檔案關掉 fileio_FileClose(fp); } int ini_ReadNextItem(FILEIO* fp, INI_ITEM_t* iniitem) { //讀取檔案 char buf[INI_MAXLINESIZE+1]; char *str = ""; char *str1, *str2; ini_InitialItem(iniitem); //把iniitem設為預設值 在20行 iniitem->itemname[0] = iniitem->itemvalue[0] = '\0'; //read a line while (!fileio_IsFileEnd(fp)) //判斷檔案室否已經到達結尾 在318行 { str = fileio_ReadLine(fp, buf, INI_MAXLINESIZE); //讀取一行檔案內容 在232行 str = ini_RemoveSpace(ini_RemoveComment(str)); //改成電腦讀取方式 並且去除空格等無意義字元 if (strlen(str) != 0) break; //如果字串長度為零 就再重讀一行 } if(strlen(str) == 0) //如果出來還是為零 代表檔案是空的 return INI_FILEEND; //回傳INI_FILEEND errcode_SetErrStr(str); //parse the line // [XXXXXXXX] if ((str[0] == '[') && (str[strlen(str)-1] == ']')){ //如果讀取的檔案前後有[] 代表為itemname errcode_SetErrGroup(str); str[strlen(str)-1] = '\0'; strcpy(iniitem->itemname, ini_RemoveSpace(&str[1])); //把讀進來的字放到itemname去 iniitem->type = INI_GROUPTITLE; //型態設為INI_GROUPTITLE } // XXXX = YYYYY else if((ini_DivideString(str, &str1, &str2, "=")) != INI_DIVIDE_FAIL){ //分割字串以"="為分割點 在40行 strcpy(iniitem->itemname, str1); //前面為itemname strcpy(iniitem->itemvalue, str2); //後面為itemvalue iniitem->type = INI_GROUPITEM; //型態設為INI_GROUPITEM } else iniitem->type = INI_UNKNOWNITEM; //其他設定為INI_UNKNOWNITEM return SUCCESS; } //==================== Parsing Functions ====================>: bool ini_IsGroup(INI_ITEM_t* item, const char* title) { //判斷itemname是否為title if (_stricmp(item->itemname, title) == 0) return true; return false; } bool ini_IsItem(INI_ITEM_t* item, const char* name) { //判斷itemname是否為name if (_stricmp(item->itemname, name) == 0) return true; return false; } int ini_GetCH(char *str, int *ch) //抓出channel的編號 { int status; status = ini_ParseNumber_pre(str, "CH", ch); //分析字首 在92行 if(status != SUCCESS) status = ini_ParseNumber_pre(str, "Channel", ch); if(status == SUCCESS) if((*ch <= 31) && (*ch >= 0)) return SUCCESS; return INI_INVALIDCHANNEL; } /*--------------------- end of Func. for .ini Files ------------------------*/ FILEIO* fileio_FileOpen(char* filename, const char* mode) { //可以開啟zip檔 也可以正常開啟 #ifdef USE_ZZIP char str[256]; strcpy(str, mode); return zzip_fopen(filename, strcat(str, "i")); //mode | ZZIP_CASELESS #else return fopen(filename, mode); #endif } void fileio_FileClose(FILEIO* fp) { //關閉檔案用 #ifdef USE_ZZIP zzip_fclose(fp); #else fclose(fp); #endif } FILEIO_SIZE_T fileio_Read(void* buf, FILEIO_SIZE_T size, FILEIO_SIZE_T count, FILEIO* fp) { //一次讀取count個大小為size的資料 #ifdef USE_ZZIP return zzip_fread(buf, size, count, fp); #else return fread(buf, size, count, fp); #endif } char* fileio_ReadLine(FILEIO* fp, char* buf, int maxcnt) { //先讀取字元 排成一行回傳一行字 int i = 0, c; for (i=0; i<maxcnt; i++) { if ((c=fileio_GetChar(fp)) == EOF) break; //讀取檔案的字元 如果讀到EOF跳出 在298行 if ((c == '\r') || (c == '\n')) break; //如果遇到\r或\n也跳出 buf[i] = c; //其他正常字元 放入buf } buf[i] = '\0'; //遇到結尾 給一個結尾符號 //clear remaining chars in the current line if (i == maxcnt) //如果上面的迴圈不是因為遇到條件跳出的話 { while((c=fileio_GetChar(fp)) != EOF) //向後把特殊符號拿掉 不然後造成下一次讀取的錯誤 if ((c == '\r') || (c == '\n')) break; } return buf; } /* #ifdef USE_ZZIP static char INI_ReadBuf[256]; static int INI_CurChar = -1; #endif int ini_GetChar(INIFILE* fp) { #ifdef USE_ZZIP int i; if ((INI_CurChar == -1) || (INI_ReadBuf[INI_CurChar] == '\0')) { i = (int)zzip_fread(INI_ReadBuf, sizeof(INI_ReadBuf[0]), 255, fp); if (i <= 0) return EOF; INI_ReadBuf[i] = '\0'; INI_CurChar = 0; } return INI_ReadBuf[INI_CurChar++]; #else return fgetc(fp); #endif } int ini_IsFileEnd(INIFILE* fp) { #ifdef USE_ZZIP long cur_offset, end_offset; if ((INI_CurChar == -1) || (INI_ReadBuf[INI_CurChar] == '\0')) { cur_offset = zzip_tell(fp); zzip_seek(fp, 0L, SEEK_END); end_offset = zzip_tell(fp); if (cur_offset >= end_offset) return 1; zzip_seek(fp, cur_offset, SEEK_SET); } return 0; #else return feof(fp); #endif } */ int fileio_GetChar(FILEIO* fp) { //讀取檔案的字元 #ifdef USE_ZZIP char buf[1]; int i = (int)zzip_fread(buf, sizeof(buf[0]), 1, fp); if (i <= 0) return EOF; else return (int)buf[0]; #else return fgetc(fp); #endif } bool fileio_Exist(char* filename) { //檢查檔案室否存在 FILEIO* fp; if ((fp = fileio_FileOpen(filename, "r")) == NULL) return false; fileio_FileClose(fp); return true; } int fileio_IsFileEnd(FILEIO* fp) { //判斷檔案室否已經到達結尾 #ifdef USE_ZZIP FILEIO_OFF_T cur_offset, end_offset; cur_offset = zzip_tell(fp); zzip_seek(fp, 0L, SEEK_END); end_offset = zzip_tell(fp); if (cur_offset >= end_offset) return 1; zzip_seek(fp, cur_offset, SEEK_SET); return 0; #else return feof(fp); #endif } FILEIO_SIZE_T fileio_GetSize(FILEIO* fp) { //取得檔案結尾用 FILEIO_OFF_T cur_offset, end_offset; #ifdef USE_ZZIP cur_offset = zzip_tell(fp); zzip_seek(fp, 0L, SEEK_END); end_offset = zzip_tell(fp); zzip_seek(fp, cur_offset, SEEK_SET); #else cur_offset = ftell(fp); //cur_offset現在的位置 fseek(fp, 0L, SEEK_END); end_offset = ftell(fp); //end_offset為檔案結尾 fseek(fp, cur_offset, SEEK_SET); #endif return end_offset; } int fileio_Seek(FILEIO* fp, FILEIO_OFF_T offset, int origin) { //fseek 也可用於zzip #ifdef USE_ZZIP if (zzip_seek(fp, offset, origin) >= 0L) return 0; return -1; #else return fseek(fp, offset, origin); //改變檔案所在位置 #endif } FILEIO_OFF_T fileio_GetPos(FILEIO* fp) { //ftell 也可用於zzip #ifdef USE_ZZIP return zzip_tell(fp); #else return ftell(fp); //回傳檔案目前位置 #endif }
0 留言:
張貼留言