写文件头的算法流程及C代码实现
一、問題描述
?????? 將多條記錄寫入文件中,每條記錄占一行。每寫入一條記錄,要計算當前文件中所有記錄的大小(精確到字節)和記錄條數,并寫到文件的第一行(即文件頭)。為了便于區分,文件記錄的大小和文件中記錄條數各占10個字節,左對齊,不足的位補以空格。
?
二、算法流程
三、C代碼實現
/********************************************************************** * 版權所有 (C)2015, Zhou Zhaoxiong。 * * 文件名稱:WriteFileHeader.c * 文件標識:無 * 內容摘要:測試文件頭的寫入 * 其它說明:無 * 當前版本:V1.0 * 作 者:Zhou Zhaoxiong * 完成日期:20150113 * **********************************************************************/ #include #include #include // 重定義數據類型 typedef signed char INT8; typedef unsigned char UINT8; typedef unsigned int UINT32; typedef signed int INT32;// 函數聲明 void WriteToFile(UINT8 *pszContentLine); INT32 main();/********************************************************************** * 功能描述:主函數 * 輸入參數:無 * 輸出參數:無 * 返 回 值:無 * 其它說明:無 * 修改日期 版本號 修改人 修改內容 * ------------------------------------------------------------------- * 20150113 V1.0 Zhou Zhaoxiong 創建 ***********************************************************************/ INT32 main() {UINT8 szContentLine[1000] = {0};// 第一次寫文件// 拼裝寫本地文件的內容snprintf(szContentLine, sizeof(szContentLine)-1, "1234|abcd|\r\n");// 將文件內容寫入本地文件WriteToFile(szContentLine);// 第二次寫文件// 拼裝寫本地文件的內容snprintf(szContentLine, sizeof(szContentLine)-1, "5678|efgh|\r\n");// 將文件內容寫入本地文件WriteToFile(szContentLine);// 第三次寫文件// 拼裝寫本地文件的內容snprintf(szContentLine, sizeof(szContentLine)-1, "4321|dcba|\r\n");// 將文件內容寫入本地文件WriteToFile(szContentLine);return 0; // main函數返回0 }/*********************************************************************** 功能描述: 寫本地文件, 同時更新文件頭* 輸入參數: pszContentLine: 一條文件記錄* 輸出參數: 無* 返 回 值: 無* 其它說明: 文件頭的長度為20字節, 前10字節為寫入文件內容的大小, 后10字節為文件內容的條數* 修改日期 版本號 修改人 修改內容* ---------------------------------------------------------------------- * 20150113 V1.0 Zhou Zhaoxiong 創建************************************************************************/ void WriteToFile(UINT8 *pszContentLine) {INT8 szFileName[500] = {0};FILE *fp = NULL;UINT8 iIsNewCdrFile = 0;UINT8 szFileHeader[100] = {0};UINT8 szTmpBuf[50] = {0};UINT32 iSize = 0;UINT32 iCount = 0;UINT32 iLen = 0;if (NULL == pszContentLine){printf("WriteToFile: input parameter is NULL.\n");return;}snprintf(szFileName, sizeof(szFileName)-1, "/home/zhou/zhouzhaoxiong/TestFile.txt");// 判斷是否為新文件if (access(szFileName, 0) == -1){iIsNewCdrFile = 1; // 是新文件}else{iIsNewCdrFile = 0;}fp = fopen(szFileName, "a+");if (fp == NULL){printf("WriteToFile: open file failed, file=%s\n", szFileName);return;}// 如果是新文件, 先寫文件頭if (iIsNewCdrFile == 1){// 新話單文件, 寫入文件頭memset(szFileHeader, 0x00, sizeof(szFileHeader));memset(szFileHeader, ' ', 20); strcat(szFileHeader, "\r\n"); // 回車換行符// 文件頭第一部分, 文件內容的大小sprintf(szTmpBuf, "%d", strlen(pszContentLine)-2); // 要去掉最后的回車換行符的大小, 因此這里要減去2memcpy(szFileHeader, szTmpBuf, strlen(szTmpBuf));// 文件頭第二部分, 文件內容的條數sprintf(szTmpBuf, "%d", 1); // 寫入第一條memcpy(szFileHeader+10, szTmpBuf, strlen(szTmpBuf));printf("WriteToFile: now write header to file, Count of content=%s\n", szTmpBuf);fputs(szFileHeader, fp);}fputs(pszContentLine, fp);fflush(fp);fclose(fp);fp = NULL; // 寫入完畢要在關閉文件的同時置文件指針為空// 更新文件頭if (iIsNewCdrFile == 0) // 文件已存在{fp = fopen(szFileName, "r+");if (fp == NULL){printf("WriteToFile: open file for updating header failed, file=%s\n", szFileName);return;}// 已有話單文件, 更新文件頭memset(szFileHeader, 0x00, sizeof(szFileHeader));fseek(fp, 0, SEEK_SET); // 文件第一行fread(szFileHeader, 20, 1, fp);fflush(fp);// 更新文件內容的大小memset(szTmpBuf, 0x00, sizeof(szTmpBuf));memcpy(szTmpBuf, szFileHeader, 10);iSize = atoi(szTmpBuf); // 原大小sprintf(szTmpBuf, "%d", iSize+strlen(pszContentLine)-2);iLen = strlen(szTmpBuf);memcpy(szFileHeader, szTmpBuf, iLen);// 更新文件內容的條數memset(szTmpBuf, 0x00, sizeof(szTmpBuf));memcpy(szTmpBuf, szFileHeader+10, 10);iCount = atoi(szTmpBuf);sprintf(szTmpBuf, "%d", iCount+1);iLen = strlen(szTmpBuf);memcpy(szFileHeader+10, szTmpBuf, iLen);printf("WriteToFile: now update file header, Count of content=%s\n", szTmpBuf);fseek(fp, 0, SEEK_SET);fwrite(szFileHeader, 20, 1, fp);fflush(fp);fclose(fp);fp = NULL;} }?
四、程序說明
??????? (1) 本程序在Linux環境下用makefile文件進行編譯,makefile文件的內容如下:
WriteFileHeader : WriteFileHeader.c
?????? gcc -c -g WriteFileHeader.c
?????? gcc -g -o release/WriteFileHeader WriteFileHeader.o
?????? rm *.o
??????? (2) 本程序中使用了多個文件處理函數,如:fopen、fputs、fflush、fclose、fseek、fread、fwrite等。各位讀者可以據此體會不同文件處理函數的用法。
??????? (3) 本程序演示了三次文件記錄的寫入過程,大家可以根據自身所需用不同的記錄來對程序進行測試。
?
五、程序運行結果
??????? 用makefile文件對程序進行編譯之后,轉到release目錄下,執行“WriteFileHeader”命令,結果如下:
WriteToFile: now write header to file, Count of content=1
WriteToFile: now update file header, Count of content=2
WriteToFile: now update file header, Count of content=3
?????? 查看TestFile.txt文件,內容如下:
---------------------------------------
2016年4月28日修改程序:
/********************************************************************** * 版權所有 (C)2015, Zhou Zhaoxiong。 * * 文件名稱:WriteFileHeader.c * 文件標識:無 * 內容摘要:測試文件頭的寫入 * 其它說明:無 * 當前版本:V1.0 * 作 者:Zhou Zhaoxiong * 完成日期:20150113 * **********************************************************************/ #include #include #include #include // 重定義數據類型 typedef signed char INT8; typedef unsigned char UINT8; typedef unsigned short int UINT16; typedef unsigned int UINT32; typedef signed int INT32; typedef long int LONG;// 時間結構體 typedef struct {UINT8 second; /* 0-59 */UINT8 minute; /* 0-59 */UINT8 hour; /* 0-23 */UINT8 day; /* 1-31 */UINT8 month; /* 1-12 */UINT16 year; /* 1994-2099 */UINT8 week; /* 1-7 */UINT8 Count10ms; /* 0-99 */ } ClockStruc;// 函數聲明 void WriteToFile(UINT8 *pszContentLine); void WriteNewFileHeader(FILE *fp, UINT8 *pszContentLine); void UpdateFileHeader(INT8 *pszFileName, UINT8 *pszContentLine); void CurrentTime(ClockStruc *ptTime);/********************************************************************** * 功能描述:主函數 * 輸入參數:無 * 輸出參數:無 * 返 回 值:無 * 其它說明:無 * 修改日期 版本號 修改人 修改內容 * ------------------------------------------------------------------- * 20150113 V1.0 Zhou Zhaoxiong 創建 ***********************************************************************/ INT32 main() {UINT8 szContentLine[1000] = {0};// 第一次寫文件// 拼裝寫本地文件的內容snprintf(szContentLine, sizeof(szContentLine)-1, "1234|abcd|\r\n");// 將文件內容寫入本地文件WriteToFile(szContentLine);// 第二次寫文件// 拼裝寫本地文件的內容snprintf(szContentLine, sizeof(szContentLine)-1, "5678|efgh|\r\n");// 將文件內容寫入本地文件WriteToFile(szContentLine);// 第三次寫文件// 拼裝寫本地文件的內容snprintf(szContentLine, sizeof(szContentLine)-1, "4321|dcba|\r\n");// 將文件內容寫入本地文件WriteToFile(szContentLine);// 第四次寫文件// 拼裝寫本地文件的內容snprintf(szContentLine, sizeof(szContentLine)-1, "1234567890\r\n");// 將文件內容寫入本地文件WriteToFile(szContentLine);return 0; }/*********************************************************************** 功能描述: 寫本地文件, 同時更新文件頭* 輸入參數: pszContentLine: 一條文件記錄* 輸出參數: 無* 返 回 值: 無* 其它說明: 文件頭的長度為50字節, 前10字節為寫入文件內容的大小, 11-20字節為文件內容的條數, 21-40字節為寫入最后一條文件記錄時的時間* 修改日期 版本號 修改人 修改內容* ----------------------------------------------------------------------* 20150113 V1.0 Zhou Zhaoxiong 創建**********************************************************************/ void WriteToFile(UINT8 *pszContentLine) {INT8 szFileName[500] = {0};FILE *fp = NULL;UINT8 *pszHomePath = NULL;UINT8 iIsNewCdrFile = 0;if (NULL == pszContentLine){printf("WriteToFile: input parameter is NULL.\n");return;}pszHomePath = (UINT8 *)getenv("HOME"); // 獲取當前用戶所在的主目錄if (pszHomePath == NULL){return;}// 獲取帶路徑的文件名snprintf(szFileName, sizeof(szFileName)-1, "%s/zhouzhaoxiong/zzx/TestFile.txt", pszHomePath);// 判斷是否為新文件if (access(szFileName, 0) == -1){iIsNewCdrFile = 1; // 是新文件}else{iIsNewCdrFile = 0;}fp = fopen(szFileName, "a+");if (fp == NULL){printf("WriteToFile: open file failed, file=%s\n", szFileName);return;}// 如果是新文件, 先寫文件頭if (iIsNewCdrFile == 1){WriteNewFileHeader(fp, pszContentLine);}fputs(pszContentLine, fp);fflush(fp);fclose(fp);fp = NULL; // 寫入完畢要在關閉文件的同時置文件指針為空// 更新文件頭if (iIsNewCdrFile == 0) // 文件已存在{UpdateFileHeader(szFileName, pszContentLine);} }/*********************************************************************** 功能描述: 首次寫文件頭* 輸入參數: pszContentLine: 一條文件記錄* 輸出參數: 無* 返 回 值: 無* 其它說明: 無* 修改日期 版本號 修改人 修改內容* ----------------------------------------------------------------------* 20160428 V1.0 Zhou Zhaoxiong 創建*********************************************************************/ void WriteNewFileHeader(FILE *fp, UINT8 *pszContentLine) {UINT8 szFileHeader[100] = {0};UINT8 szTmpBuf[50] = {0};ClockStruc tCurTime = {0};if (NULL == fp || NULL == pszContentLine){printf("WriteNewFileHeader: input parameter(s) is NULL.\n");return;}// 新文件, 寫入文件頭memset(szFileHeader, ' ', 40); strcat(szFileHeader, "\r\n"); // 回車換行符// 文件頭第一部分, 文件內容的大小snprintf(szTmpBuf, sizeof(szTmpBuf)-1, "%d", strlen(pszContentLine)-2); // 要去掉最后的回車換行符的大小, 因此這里要減去2memcpy(szFileHeader, szTmpBuf, strlen(szTmpBuf));// 文件頭第二部分, 文件內容的條數snprintf(szTmpBuf, sizeof(szTmpBuf)-1, "%d", 1); // 寫入第一條memcpy(szFileHeader+10, szTmpBuf, strlen(szTmpBuf));// 文件頭第三部分, 寫入最后一條文件記錄時的時間CurrentTime(&tCurTime); memset(szTmpBuf, 0x00, sizeof(szTmpBuf));snprintf(szTmpBuf, sizeof(szTmpBuf)-1, "%d.%d.%d %d:%d:%d", tCurTime.year, tCurTime.month, tCurTime.day, tCurTime.hour, tCurTime.minute, tCurTime.second);memcpy(szFileHeader+20, szTmpBuf, strlen(szTmpBuf));printf("WriteNewFileHeader: now write new file header, Count of content=%d\n", 1);fputs(szFileHeader, fp); }/*********************************************************************** 功能描述: 更新文件頭* 輸入參數: pszFileName: 文件名pszContentLine: 一條文件記錄* 輸出參數: 無* 返 回 值: 無* 其它說明: 無* 修改日期 版本號 修改人 修改內容* ----------------------------------------------------------------------* 20160428 V1.0 Zhou Zhaoxiong 創建*********************************************************************/ void UpdateFileHeader(INT8 *pszFileName, UINT8 *pszContentLine) {UINT8 szFileHeader[100] = {0};UINT8 szTmpBuf[50] = {0};FILE *fp = NULL;UINT32 iSize = 0;UINT32 iLen = 0;UINT32 iCount = 0;ClockStruc tCurTime = {0};if (NULL == pszFileName || NULL == pszContentLine){printf("UpdateFileHeader: input parameter(s) is NULL.\n");return;}fp = fopen(pszFileName, "r+");if (fp == NULL){printf("UpdateFileHeader: open file for updating header failed, file=%s\n", pszFileName);return;}// 已有文件, 更新文件頭memset(szFileHeader, 0x00, sizeof(szFileHeader));fseek(fp, 0, SEEK_SET); // 文件第一行fread(szFileHeader, 40, 1, fp);fflush(fp);// 更新文件內容的大小memset(szTmpBuf, 0x00, sizeof(szTmpBuf));memcpy(szTmpBuf, szFileHeader, 10);iSize = atoi(szTmpBuf); // 原大小snprintf(szTmpBuf, sizeof(szTmpBuf)-1, "%d", iSize+strlen(pszContentLine)-2);iLen = strlen(szTmpBuf);memcpy(szFileHeader, szTmpBuf, iLen);// 更新文件內容的條數memset(szTmpBuf, 0x00, sizeof(szTmpBuf));memcpy(szTmpBuf, szFileHeader+10, 10);iCount = atoi(szTmpBuf);snprintf(szTmpBuf, sizeof(szTmpBuf)-1, "%d", iCount+1);iLen = strlen(szTmpBuf);memcpy(szFileHeader+10, szTmpBuf, iLen);// 更新時間CurrentTime(&tCurTime); memset(szTmpBuf, 0x00, sizeof(szTmpBuf));snprintf(szTmpBuf, sizeof(szTmpBuf)-1, "%04d.%02d.%02d %02d:%02d:%02d", tCurTime.year, tCurTime.month, tCurTime.day, tCurTime.hour, tCurTime.minute, tCurTime.second);iLen = strlen(szTmpBuf);memcpy(szFileHeader+20, szTmpBuf, iLen);printf("UpdateFileHeader: now update file header, Count of content=%d\n", iCount+1);fseek(fp, 0, SEEK_SET);fwrite(szFileHeader, 40, 1, fp);fflush(fp);fclose(fp);fp = NULL; }/********************************************************************** * 功能描述:當前時間 * 輸入參數:ptTime-時間結構體 * 輸出參數:ptTime-時間結構體 * 返 回 值:無 * 其它說明:無 * 修改日期 版本號 修改人 修改內容 * ------------------------------------------------------------------- * 20160428 V1.0 Zhou Zhaoxiong 創建 ***********************************************************************/ void CurrentTime(ClockStruc *ptTime) {LONG dt = 0;struct tm *tm1 = NULL;struct timeval tp = {0};// get real clock from systemgettimeofday(&tp, NULL);dt = tp.tv_sec;tm1 = localtime(&dt);ptTime->Count10ms = tp.tv_usec / 10000;ptTime->year = (UINT16)(tm1->tm_year + 1900);ptTime->month = (UINT8)tm1->tm_mon + 1;ptTime->day = (UINT8)tm1->tm_mday;ptTime->hour = (UINT8)tm1->tm_hour;ptTime->minute = (UINT8)tm1->tm_min;ptTime->second = (UINT8)tm1->tm_sec;ptTime->week = (UINT8)tm1->tm_wday;if (ptTime->week == 0) // Sunday{ptTime->week = 7;} }總結
以上是生活随笔為你收集整理的写文件头的算法流程及C代码实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: List集合中对象的排序
- 下一篇: Lower Power with CPF