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

posted @ 2016-04-30 01:19  Harley_Quinn  阅读(2479)  评论(0编辑  收藏  举报