http://www.cnblogs.com/Solstice/archive/2011/07/17/2108715.html
看了這篇博客有感而發。
就個人而言我是典型的從C到C++的類型,並且逐漸去掉C風格,用C++風格代替,所以幾乎不用FILE*讀寫。
iostream一個顯著的優點是流運算符,我以前做一些數學計算類程序時深刻體會到它的優點,不用像printf一樣針對特定類型編寫特定的format,流運算符還能被重載,方便將說明結果輸出到文本文檔中,能體現面向對象程序設計的優越性。(當然就像鏈接中提到的,用iostream控制格式反倒非常麻煩,不如format簡短,還能被外部配置文件利用。)
此時,除非是程序對IO性能要求很高,我還是會選用iostream。
但是,在讀寫特定格式二進制文件時(比如我目前在做的圖像處理),兩者在語法上差異不大,但是效率上FILE*好多了,即使關閉stdio同步。
http://www.cplusplus.com/reference/cstdio/,C++官網直接看各函數的使用方式,這里就不詳述了,還是用個典型例子說明。
// 功能:讀取BMP圖像文件頭,將文件頭信息輸出到文本文檔中 #include <cstdio> typedef unsigned short WORD; typedef unsigned long DWORD; int main() { char szFileName[] = "C:\\Miss2.bmp"; FILE* fp = fopen(szFileName, "r"); if (!fp) { fprintf(stdout, "讀取失敗!\n"); return -1; } WORD bfType; // 文件類型,必須為“BM” fread(&bfType, sizeof(bfType), 1, fp); if (!(bfType == (int)'B' + ((int)'M' << 8))) { fprintf(stdout, "文件類型不正確!\n"); return -1; } DWORD bfSize; // 指定位圖文件的大小,以字節表示 fread(&bfSize, sizeof(bfSize), 1, fp); // 移動指針跳過文件頭的兩個保留字,SEEK_SET為起始位置 fseek(fp, sizeof(WORD) * 3 + sizeof(DWORD), SEEK_SET); //fseek(fp, sizeof(WORD) * 2, SEEK_CUR); // 有誤? DWORD bfOffBits; // 指定從實際圖像數據到文件頭起始的偏移字節數 fread(&bfOffBits, sizeof(bfOffBits), 1, fp); fclose(fp); // 把文件頭信息寫入文檔中 fp = fopen("C:\\Miss2.bmp文件頭描述.txt", "w"); fprintf(fp, "位圖文件大小:\t%ld\n", (long)bfSize); fprintf(fp, "位圖數據大小:\t%ld\n", (long)(bfSize - bfOffBits)); fclose(fp); return 0; }
從代碼中可以看出有不少重復代碼,以多次用到的fread為例。
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
size:單個數據類型的大小,一般直接用sizeof(T);
count:數據元素個數。(注意,如果是要讀取到字符數組,由於字符數組要以'\0'結尾,所以此時count應為strlen(sz),其中sz為數組名,然后在數組的末尾置為'\0')
如果封裝成模板函數,template<typename T, int N>會簡潔許多。
就像開頭鏈接中建議的,實際可以自己封裝下FILE指針,最好還是用現成的IO庫。
至於要用stream方式做logging以后再看看吧,暫時用不着先不研究。