使用FILE指針讀寫文件


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以后再看看吧,暫時用不着先不研究。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM