最近在做一个从groundtruth_rect.txt中读取按行存储的矩形元素(x, y, w, h),文本存储的格式如下:

310,102,39,50
308,100,39,50
306,99,39,50
306,98,38,49
304,97,38,49
303,96,37,48

一般处理这种带格式的存储数据,我最喜欢的就是C语言中的格式化的输出和输入fprintf和fscanf,因为知道格式,所以一个循环反复就可以将矩形从txt中提取出来,非常的简单方便。可是当我定义了一个FILE* file = fopen("groundtruth_rect.txt","r");时程序总是有一个bugger,编译器(VS2010)输出的错误信息是:

error C2679: 二进制“=”: 没有找到接受“FILE *”类型的右操作数的运算符(或没有可接受的转换)
1>          C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\winbase.h(6618): 可能是“_WIN32_FIND_DATAA &_WIN32_FIND_DATAA::operator =(const _WIN32_FIND_DATAA &)”


调来调去也没有找到错误原因,在网上也没有找到相关的提示。我猜测原因可能是由于在程序中定义了和包含了一下东西以方便我能够进行文件夹下的序列图像的路径获取:


#define _AFXDLL

#define _WIN32_WINNT 0x0502 

#include <WinBase.h>

#include <ShlObj.h>

#include <afxdlgs.h>

#include <atlstr.h>


(如果有“同道中人”希望能指点一二)

如果去掉上面的那一部分所有的bugger就消失了。因为必须用到上面获取路径的办法,所以只好放弃使用FILE *这种C语言的文件操作,转而使用C++提供的文件操作方法:

string line;

getline(file, line);

istringstream linestream(line);

string x1, y1, w1, h1;

getline(linestream, x1, ',');

getline(linestream, y1, ',');

getline(linestream, w1, ',');

getline(linestream, h1, ',');

int x = atoi(x1.c_str());

int y = atoi(y1.c_str());

int w = atoi(w1.c_str());

int h = atoi(h1.c_str());

groundtruth_rect[i] = Rect(x, y, w, h);

上面这段代码是一种比较好的方法,在运行中没有出现错误。采用的完全是按照字符来对待,以 ‘,’ 作为行的getline的结尾,一行一行的读取数据,然后再利用atoi()将字符串转变为数字,也就实现了格式化读取数据的目的。
下面先给出使用getline的范例
<span style="font-size:18px;">// string_getline_sample.cpp
// compile with: /EHsc
// Illustrates how to use the getline function to read a
// line of text from the keyboard.
//
// Functions:
//
// getline Returns a string from the input stream.
////////////////////////////////////////////////////////////////////// #pragma warning(disable:4786)
#include <string>
#include <iostream> using namespace std ; int main()
{
string s1;
cout << "Enter a sentence (use <space> as the delimiter): ";
getline(cin,s1, ' ');
cout << "You entered: " << s1 << endl;;
}</span>

然后再给出atoi()的使用范例:atoi会把能够解释为数字的字符串转变为整形数据,从字符串的开头一直到第一个不能被解释为数字的字符为止,比如“\0”等。


<span style="font-size:18px;">// crt_atoi.c
// This program shows how numbers
// stored as strings can be converted to
// numeric values using the atoi functions. #include <stdlib.h>
#include <stdio.h>
#include <errno.h> int main( void )
{
char *str = NULL;
int value = 0; // An example of the atoi function.
str = " -2309 ";
value = atoi( str );
printf( "Function: atoi( \"%s\" ) = %d\n", str, value ); // Another example of the atoi function.
str = "31412764";
value = atoi( str );
printf( "Function: atoi( \"%s\" ) = %d\n", str, value ); // Another example of the atoi function
// with an overflow condition occuring.
str = "3336402735171707160320";
value = atoi( str );
printf( "Function: atoi( \"%s\" ) = %d\n", str, value );
if (errno == ERANGE)
{
printf("Overflow condition occurred.\n");
}
}</span>

输出为:

Function: atoi( "  -2309 " ) = -2309
Function: atoi( "31412764" ) = 31412764
Function: atoi( "3336402735171707160320" ) = 2147483647
Overflow condition occurred.


但一开始并没有想到这种方法,而是采用了一个比较笨的办法,刚开始还能正确读取数据,可是读到一半的时候居然读出的数据全是0了,我也真是快疯了(本来痛痛快快的使用C中的格式化输入就好了,结果搞了两个小时才搞定,心情郁闷可想而知)

//int  test[4];



//test[0] = 0;

//file>>dec>>test[0];

//groundtruth_rect[i].x = test[0];



//test[1] = 0;

//file.seekg(1,ios::cur);

//file>>dec>>test[1];

//groundtruth_rect[i].y = test[1];



//test[2] = 0;

//file.seekg(1,ios::cur);

//file>>dec>>test[2];

//groundtruth_rect[i].width = test[2];



//test[3] = 0;

//file.seekg(1,ios::cur);

//file>>dec>>test[3];

//groundtruth_rect[i].height = test[3];
//file.seekg(1,ios::cur);


采用的方法是运算符>>,中间的dec是表示采用十进制的方式输入,插入器(>>)+操纵符(dec)的方式,刚开始并没有加file.seekg(1,ios::cur);进行文件的重定位,除了第一个之外后面读到的数据全是0,我就这样一步一步的通过调试(不太熟悉这个机制,又急着实现,只能盲人摸象了)。后来采用了file.seekg(1,ios::cur);来对文件的读位置进行定位,跳过了格式化作用的逗号,就这样才能正确的读入了。结果开始运行后,发现一共500多个矩形框的数据,这种方式只能读取到221个,而且读出的数据是对的,但是后面的200多个就不知道为啥读不进来了。这个bugger也依然没有解决(希望有高人指点迷津)!

有了以上的调试经历,我感觉到不能再盲人摸象,便决定对C++的典型文件操作进行一下学习和总结:

具体内容可以参看了别人的博文,我下面只对比较常用的内容进行介绍:http://blog.csdn.net/jiangxinyu/article/details/7875931 和 http://www.cnblogs.com/kzloser/archive/2012/07/16/2593133.html
不管是Linux(shell)还是windows下,一般默认打开的输入输出设备对象都会有三种:一是标准输入设备键盘缓冲区,二是标准输出设备显示器缓冲区,三是错误信息。(特别是在linux下的shell命令,很经典的对照,有兴趣的可以了解一下,输入输出重定向的方法是不是类似c++中的iostream与fstream,ofstream,ifstream)。

当然首先就是打开文件,一般都会有文本文件和二进制文件的选项,默认大都是文本文件,C语言中的“wb+” b表示为二进制,而C++中为ios::binary
C++有
操纵符 功能 输入/输出

dec 格式化为十进制数值数据 输入和输出

endl 输出一个换行符并刷新此流 输出

ends 输出一个空字符 输出

hex 格式化为十六进制数值数据 输入和输出

oct 格式化为八进制数值数据 输入和输出

setpxecision(int p) 设置浮点数的精度位数 输出
对应到C中有格式化的输入输出:%c,%d,%f,%s等等。

另外与C的文件操作方式不太一样的地方是C++管理读指针和写指针,分别可以利用seekg和seekp来设定
ios::beg:  文件开头

ios::cur:  文件当前位置

ios::end:  文件结尾
而对应到C则是fseek(),ftell等。
C的文件操作总结如下:


C++经典的文件操作如下:



*******************************************************************************************************************************************************************************************************2015-7-24

C/C++文件操作经验总结的更多相关文章

  1. Mapreduce的文件和hbase共同输入

    Mapreduce的文件和hbase共同输入 package duogemap;   import java.io.IOException;   import org.apache.hadoop.co ...

  2. mapreduce多文件输出的两方法

    mapreduce多文件输出的两方法   package duogemap;   import java.io.IOException;   import org.apache.hadoop.conf ...

  3. 01.SQLServer性能优化之----强大的文件组----分盘存储

    汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 文章内容皆自己的理解,如有不足之处欢迎指正~谢谢 前天有学弟问逆天:“逆天,有没有一种方 ...

  4. SQL Server 大数据搬迁之文件组备份还原实战

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 解决方案(Solution) 搬迁步骤(Procedure) 搬迁脚本(SQL Codes) ...

  5. SQLSERVER将一个文件组的数据移动到另一个文件组

    SQLSERVER将一个文件组的数据移动到另一个文件组 有经验的大侠可以直接忽视这篇文章~ 这个问题有经验的人都知道怎麽做,因为我们公司的数据量不大没有这个需求,也不知道怎麽做实验 今天求助了QQ群里 ...

  6. SQL Server中的高可用性(2)----文件与文件组

        在谈到SQL Server的高可用性之前,我们首先要谈一谈单实例的高可用性.在单实例的高可用性中,不可忽略的就是文件和文件组的高可用性.SQL Server允许在某些文件损坏或离线的情况下,允 ...

  7. C# ini文件操作【源码下载】

    介绍C#如何对ini文件进行读写操作,C#可以通过调用[kernel32.dll]文件中的 WritePrivateProfileString()和GetPrivateProfileString()函 ...

  8. 【小程序分享篇 一 】开发了个JAVA小程序, 用于清除内存卡或者U盘里的垃圾文件非常有用

    有一种场景, 手机内存卡空间被用光了,但又不知道哪个文件占用了太大,一个个文件夹去找又太麻烦,所以我开发了个小程序把手机所有文件(包括路径下所有层次子文件夹下的文件)进行一个排序,这样你就可以找出哪个 ...

  9. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

随机推荐

  1. 布局 Bootstrap Table的 文本内容 垂直居中

    原文:https://blog.csdn.net/peng_hong_fu/article/details/70662979 样式(注意样式优先级): #div-component-info .tab ...

  2. 用provide/inject来实现简单的vuex状态管理功能

    在开发的时候,经常会涉及到组件之间的通信.简单的有父子组件的通信,兄弟组件的通信通常可以借助Bus来进行.当然也可以用vuex来进行状态管理,但是,有时候用vuex未免有把简单的问题复杂化. 如果要进 ...

  3. lixuxmint系统定制与配置(5)-效率配置

    小书匠Linux 目录: 1.zsh安装与配置 1.1 安装 1.1.1 检查当前的终端类型 1.1.2 安装zsh 1.2 美化zsh 1.3 配置zsh 1.3.1 别名设置 2.自动登录服务器 ...

  4. AtCoder Grand Contest 011题解

    传送门 \(A\) 直接按时间排序之后贪心就可以了 const int N=1e5+5; int a[N],q[N],c,k,h,t,n,res; inline int min(R int x,R i ...

  5. vue-router 的原理

    1. hash 修改的时候:history.pushState('名字', null, '/xxx') || location.hash = '/xxx' 回退的时候:window.addEventL ...

  6. ssm + ehcache 运行异常

    异常: DEBUG [net.sf.ehcache.CacheManager@295af581] - Checking for update...DEBUG [net.sf.ehcache.Cache ...

  7. 制作OpenFOAM计算结果的gif动画【转载】

    转载自:http://blog.sina.com.cn/s/blog_6277cbbf0100niqi.html PS:对其中错误地方进行了修正 1.用ParaView将每一帧都输出成图片(File- ...

  8. const经典面试题

    1> const int age1 = 21; age1 = 100; // 编译报错 2> int const age2 = 22; 3> const int *age3 = 23 ...

  9. 关于python 的参数的汇总转

    来自:https://blog.csdn.net/gaotihong/article/details/95687282 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附 ...

  10. arcpy模块下的并行计算与大规模数据处理

    一个多星期的时间,忍着胃痛一直在做GIS 540: Spatial Programming的课程项目,导致其他方面均毫无进展,可惜可惜.在这个过程当中临时抱佛脚学习了很多Python相关的其他内容,并 ...