zoukankan      html  css  js  c++  java
  • 使用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, "读取失败!
    ");
    		return -1;
    	}
    	
    	WORD bfType;  // 文件类型,必须为“BM”
    	fread(&bfType, sizeof(bfType), 1, fp);
    	if (!(bfType == (int)'B' + ((int)'M' << 8)))
    	{
    		fprintf(stdout, "文件类型不正确!
    ");
    		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, "位图文件大小:	%ld
    ", (long)bfSize);
    	fprintf(fp, "位图数据大小:	%ld
    ", (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:数据元素个数。(注意,如果是要读取到字符数组,由于字符数组要以''结尾,所以此时count应为strlen(sz),其中sz为数组名,然后在数组的末尾置为'')

    如果封装成模板函数,template<typename T, int N>会简洁许多。

    就像开头链接中建议的,实际可以自己封装下FILE指针,最好还是用现成的IO库。

    至于要用stream方式做logging以后再看看吧,暂时用不着先不研究。

  • 相关阅读:
    深入浅出进程与线程的基本概念
    python中with的用法
    浮点型数据在内存中存储的表示
    自问问题列表以及网络答案整理
    看java源代码
    【设计模式】工厂方法
    SQL实现递归及存储过程中 In() 参数传递解决方案
    app与server联系
    添加service到SystemService硬件服务
    noproguard.classes-with-local.dex
  • 原文地址:https://www.cnblogs.com/Harley-Quinn/p/5447978.html
Copyright © 2011-2022 走看看