zoukankan      html  css  js  c++  java
  • 初探ifstream与回车换行及类型匹配等几个问题

    来源:http://blog.csdn.net/shellching/archive/2009/08/12/4438099.aspx

    #include <iostream>
    #include<fstream>
    using namespace std;
    
    /*本例:
    	1、练习ifstream、ofstream读写文件基本方法;
    	2、验证回车换行符号在文件读写中的状态和作用;
    	3、验证几种判断文件末尾的方法;
    	4、验证几种解决ifstream对读入类型不匹配数据的处理方法
    
    回车与换行符:	
    	字符    名称                   ASCII值    控制字符 
    	'\n'    换行(New line)           010     LF (Line Feed)
    	'\r'    回车(Carriage return)    013     CR (Carriage Return) 
    	
    杨小进 0:31 2009-8-12
    */
    
    //创建输入文件,为练习准备
    void createFile(char *fname)
    {
    	ofstream ofs(fname);
    	ofs << "aaaaa\n";
    	ofs << "bbbbb\n";
    	ofs << "11111\n";
    	ofs << "22222\n";
    	ofs.close();
    }
    
    //获取文件长度字节,会得到比输入更多的字节,因为 \n 被转换为 \r\n
    int getFileLen(char *fname)
    {
    	ifstream ifs(fname);
    	ifs.seekg(0, ios::end);		//移动文件指针到末尾
    	int n = ifs.tellg();		//获取文件长度字节
    	ifs.seekg(ios::beg);		//恢复指针到开始,对于接下来继续读有用
    	ifs.close();
    	return n;
    }
    
    //用read函数文本模式下读取文件,读到字节数小于真实文件大小,
    //因为系统读 \r\n 时又转换为 \n, 只是\n被读进来了
    //若是binary模式,则会读到实际文件大小的字节
    void readFileRead(char *fname, ios_base::openmode om = ios_base::in)
    {
    	int n = getFileLen(fname);
    	ifstream ifs(fname, om);
    
    	char *pc = new char[n+1];
    	memset(pc, 0, sizeof(char)*(n+1) );
    	ifs.read(pc, n);
    	if(om & ios_base::binary)
    	{
    		cout << " binary模式";
    	}
    	cout << " read()读取了"<< ifs.gcount() << "字节:\n";	
    	cout << pc;
    	delete pc;
    	ifs.close();
    }
    
    //使用流提取符号读取文件,不管是何种模式,空白字符都会被 >> 略过
    void readFileExtranction(char *fname)
    {
    	ifstream ifs(fname, ios_base::binary);
    	char c;
    	cout << "binary模式 >>读取:\n";
    	while(!ifs.eof())
    	{
    		ifs >> c;				
    		cout << c << "_";
    	}
    	ifs.close();
    }
    
    //使用Get在文本模式下读取文件内容,对于"\r\n"多跳过一个字符只读进'\n',指针移到'\n'后
    //若在binary模式则是按照真实数据读取'\r','\n';
    void readFileGet(char *fname, ios_base::openmode om = ios_base::in)
    {
    	ifstream ifs(fname, om);
    	char c;
    	if(om & ios_base::binary)
    	{
    		cout << " binary模式";
    	}
    	cout << " get()从第5字节开始读取3个字符:\n十进制:";
    	ifs.seekg(4, ios::beg);			
    	ifs.get(c);		        //读取第5字节,为'a'
    	cout << int(c) << "_";	
    	ifs.get(c);		//读取下一个字节应为13 = '\r',实际读进10 = '\n'
    	cout << int(c) << "_";	//若在binary模式下则是13 ='\r'
    	ifs.get(c);		//读取下一个字节,为'b',若是binary则是10='\n'
    	cout << int(c) << "_";
    	ifs.close();
    }
    
    //使用Peek读取文件内容,文本模式下对于"\r\n"读进'\n';
    //在binary模式下,对于"\r\n"则会读进'\r',peek始终都不会移动文件指针
    void readFilePeek(char *fname, ios_base::openmode om = ios_base::in)
    {
    	ifstream ifs(fname, om);
    	//ifstream ifs3("input.txt", ios_base::binary);
    	char c;
    	if(om & ios_base::binary)
    	{
    		cout << " binary模式";
    	}
    	cout << " peek()读取第6、7、8字节:\n";
    	ifs.seekg(5, ios::beg);			
    	c = ifs.peek();			//读取第6字节应为13 = '\r',实际上读进10 ='\n'
    	cout << int(c) << "_";	        //若在binary模式则是13 ='\r'
    	ifs.seekg(6, ios::beg);			
    	c = ifs.peek();			//读取第7字节,为10 ='\n'
    	cout << int(c) << "_";
    	ifs.seekg(7, ios::beg);			
    	c = ifs.peek();			//读取第8字节,为'b'
    	cout << int(c) << "_";
    	ifs.close();
    }
    
    //通过eof()判断文件结束,若某行只有回车也算是一行,即使在文件尾部
    void getOverEof(char *fname)
    {
    	ifstream ifs(fname);
    	string str;
    	int i = 0;
    	cout << " eof()判断文件结束";
    	while(!ifs.eof())					
    	{
    		getline(ifs, str);				
    		cout << "\n第" << ++i <<"行长度 " << str.length() << " : " << str;
    	}
    	ifs.close();
    }
    
    //通过good()判断文件结束,同eof,若某行只有回车也算是一行,即使在文件尾部
    //因为使用了binary模式,所以getline比平时多读入一个字符'\r',忽略'\n'
    void getOverGood(char *fname)
    {
    	ifstream ifs(fname, ios_base::binary);
    	int i = 0;
    	string str;
    	
    	cout << " binary模式 good()判断文件结束";
    	while(ifs.good())
    	{	
    		getline(ifs, str);
    		cout << "\n第" << ++i <<"行长度 " << str.length() << " : " << str;
    		cout << " 第6字节" << int(str[5]);
    	}
    	ifs.close();
    }
    
    //通过getline()判断文件结束,只有回车且在文件末尾的空行不算一行
    void getOverGetline(char *fname)
    {
    	ifstream ifs("input.txt");
    	int i = 0;
    	string str;
    	
    	cout << " getline()判断文件结束";
    	while(getline(ifs, str))			
    	{	
    		cout << "\n第" << ++i <<"行长度 " << str.length() << " : " << str;
    	}
    	ifs.close();
    }
    
    //使用ifstream的提取符号从文本文件读入某种类型数据例如float或double时,
    //若遇到字符串或其它非数字符号会发生错误,造成死循环,所以需要特别处理
    bool readErr(char *fname)
    { 
        cout << "不匹配数据类型处理:";
        ifstream ifs(fname);      
    	
    	if( !ifs )                            
    	{
    		cout << "\n打开文件 " << fname << " 失败\n";
    		return false;
    	}
    	
        int count=0;                                            
        int  dVal, sum=0;                                        
    	
        while( !ifs.eof() )                               
    	{
    		ifs >> dVal;
    		
    		if(ifs.fail())	//错误判断,使用"!ifs"也可以,但是"ifs.bad()"不行
    		{
    			ifs.clear();	//清楚错误标志
    			ifs.ignore(1);	//忽略当前非预期字符
    			continue;	//继续读取下一个
    		}
    		else
    		{
    		        cout << "\n第 " << ++count << "个数: " <<  dVal; 
    			  sum += dVal;                                  
    		}
    	}
    	
            ifs.close();            
        
            cout << "\n总共 " << count << " 个数,"
             << " 和为" << sum << endl;    
            return true;
    }
    
    int main()
    {
    	char fname[] = "input.txt";
    	createFile(fname);
    	
    	cout << "文件长度:" << getFileLen(fname) << " 字节";
    	
    	cout << "\n-----------------------";
    	
    	readFileRead(fname);
    	
    	cout << "\n-----------------------";
    	
    	readFileRead(fname, ios_base::binary);
    	
    	cout << "\n-----------------------";
    	
    	readFileExtranction(fname);
    	
    	cout << "\n-----------------------";
    	
    	readFileGet(fname);
    	
    	cout << "\n-----------------------";
    	
    	readFileGet(fname, ios_base::binary);
    	
    	cout << "\n-----------------------";
    	
    	readFilePeek(fname);
    	
    	cout << "\n-----------------------";
    	
    	readFilePeek(fname, ios_base::binary);
    	
    	cout << "\n-----------------------";
    	
    	getOverEof(fname);
    	
    	cout << "\n-----------------------";
    	
    	getOverGood(fname);
    	
    	cout << "\n-----------------------";
    	
    	getOverGetline(fname);
    	
    	/*
    	总结:windows系统中使用ofstream写文本文件时系统会把'\n'转换为'\n''\r'两个字符写入文件;
    	若是单写入'\r'则不会做上述转换;通常读取时会相应把'\n''\r'两个字符转换为'\n';
    	对于文本中单独的'\n'和'\r'读取时不会作特别转换,作为一个字符读出;
    	使用流输入符号">>"读取字符时,无论使用何种模式打开文件,都会忽略空白字符\n\r等;
    	使用get和peek读取时,若在文本模式下,对于文本中的"\r\n"只是作为一个字符'\n'对待;
    	get和peek,若在二进制模式下,对于文本中的"\r\n"作为两个字符对待;
    	getline在文本模式下忽略"\r\n",但是在binary模式下会忽略'\n',而不会忽略'\r';
    	*/
    	
    	cout << "\n-----------------------";
    	
    	readErr(fname);
    	
    	cout << endl;
    	return 0;
    }
    
  • 相关阅读:
    【转】 linux iio子系统
    【转】eclipse -- the project was not built due to a resource exists with a different case...
    Android常用的一些make命令(转载)--不错
    【转】Android Recovery模式
    chain rule 到 Markov chain
    chain rule 到 Markov chain
    贝叶斯统计(Bayesian statistics) vs 频率统计(Frequentist statistics):marginal likelihood(边缘似然)
    贝叶斯统计(Bayesian statistics) vs 频率统计(Frequentist statistics):marginal likelihood(边缘似然)
    企业文化与发展战略
    企业文化与发展战略
  • 原文地址:https://www.cnblogs.com/dabaopku/p/1725343.html
Copyright © 2011-2022 走看看