最近在做一个从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. 开始编写Makefile

    1.Makefile 的编写规则一 目标列表:关联性列表 命令列表 目标列表:可以是多个以空格隔开多个目标文件 关联列表页称为先决条件:同样是用个或多个空格分开的目标文件 命令列表:用<tab& ...

  2. Python逆向(三)—— Python编译运行及反汇编

    一.前言 前期我们已经对python的运行原理以及运行过程中产生的文件结构有了了解.本节,我们将结合具体的例子来实践python运行,编译,反编译的过程,并对前些章节中可能遗漏的具体细节进行补充. 二 ...

  3. Hadoop 副本放置策略的源码阅读和设置

    本文通过MetaWeblog自动发布,原文及更新链接:https://extendswind.top/posts/technical/hadoop_block_placement_policy 大多数 ...

  4. 说说AutoMapper那些事

    项目中用到了DTO与Model之间的转换,因为model项目比较多,所以需要使用工具或者代码来实现快速的转换.AutoMapper就是一个很好的基于约定的object-object mapper.映射 ...

  5. Linux----添加zabbix-agent

    1.zabbxi-agent安装及配置 1.1 获取官方zabbix源 [root@localhost ~]# rpm -ivh http://repo.zabbix.com/zabbix/3.4/r ...

  6. PostgreSQL定时自动备份

    PostgreSQL定时自动备份 简介 PostgreSQL数据库中未提供数据库的定时备份功能,所以需要结合备份和定时job功能来共同实现. 这里我选取了2种定时job方式,crontab是Linux ...

  7. Flink实时处理并将结果写入ElasticSearch实战

    参考原博客: https://blog.csdn.net/weixin_44516305/article/details/90258883 1 需求分析 使用Flink对实时数据流进行实时处理,并将处 ...

  8. CMU Database Systems - Concurrency Control Theory

    并发控制是数据库理论里面最难的课题之一 并发控制首先了解一下事务,transaction 定义如下, 其实transaction关键是,要满足ACID属性, 左边的正式的定义,由于的intuitive ...

  9. Ubuntu16.04下升级Python到3.6.5

    本文链接:https://blog.csdn.net/chaiyu2002/article/details/82698376原帖存于IT老兵博客.Ubuntu16.04下升级Python到3.6.5 ...

  10. windows中kill端口为8080的进程(或子进程)

    1.netstat -aon|findstr "8080" 查出8080端口被9436进程占用 2.查看PID对应的进程 tasklist|findstr "9436&q ...