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