输入输出流与文件读写

输出输出流

“流”是一种抽象的形态,指的是计算机里的数据从一个对象流向另一个对象。

流类库的结构

ios_base类,表示流类的一般特征。

ios类,继承与ios_base类,其中包含一个指向streambuf对象的指针成员。

ostream类,ios的派生类,提供了输出方法。

istream类,ios的派生类,提供了输入方法。

iostream,是istream和ostream的子类,既可以输入又可以输出。

文件处理相关类

ifstream,提供文件输入方法。

ofstream,提供了文件输出方法。

fstream,提供了文件输入和输出方法。

cout与cin

在输入输出流类库中,操作符>>和<<被重载用于进行数据的输入和输出。

cout输出

<<, 插入运算符。

put,ostream类的方法,用于字符的输出。

write,ostream类的方法,用于字符串的输出。

int main()
{
	//	put输出字符
	cout.put('A');
	cout.put(97); // 输出 'a'
	cout.put('B').put('C').put('\n');

	//	write输出字符串,第二个参数指定输出的长度
	char c[] = "Hello C++!";
	cout.write(c, strlen(c)).put('\n'); // cout << c << endl;
	cout.write(c, 5).put('\n'); 
	c[10] = 'X';
	cout.write(c, 11).put('\n'); //	write 输出指定长度的字符串,即使字符数组没有'\0'也能正常输出。
	cout << c << endl;	//	<< 输出到第一个字符串结束标识,如果字符数组没有'\0'会输出乱码。

	return 0;
}

cin输入

>>,提取运算符。

get,istream类的方法,提取字符。

getline,istream类的方法,提取一行字符。

/*
	cin 的工作方式:
		先检查缓冲区中是否有数据,有则提取,无则提示输入。
	>> 与get、getline的主要区别
		>> 提取时会从第一个非' '和'\n'的字符开始提取,之前的' '和'\n'会被忽略掉。
		get、getline提取数据时,不会忽略任何字符。
*/

int main()
{
	char c1;
	char c2[30];
	cout << "使用 >> 提取一个字符:" << endl;
	cin >> c1;
	cout << "c1: " << c1 << endl;
	
	cout << "使用 >> 提取字符串:" << endl;
	cin >> c2;
	cout << "c2: " << c2 << endl;

	cout << "使用 get 方法提取字符:" << endl;
	cin.ignore();	//	忽略一个字符
	cin.get(c1);
	cout << "c1: " << c1 << endl;
	
	cout << "使用 getline 方法提取一行字符串:" << endl;
	cin.ignore();	
	/*
		getline可以读取一行数据(以换行符结束,允许包含空格)
		第一个参数是存放字符串的首地址,第二个参数是要读取字符串的长度。
	*/
	cin.getline(c2, 30); 
	cout << "c2: " << c2 << endl;

	
	return 0;
}

格式化输入输出

两种格式化的实现方式:

流控制符,setw、setfill、setprecision、hex、oct、dec等,需要包含iomanip头文件。

成员函数,width、fill、precision等,不需要包含iomanip头文件就可以使用。

输出宽度控制,setw和width, 只对下一次有效。

设置填充字符,setfill和fill,永久有效,直到被更改。

fill可以返回当前填充字符,setfill不能。

输出精度控制,setprecison和precision,永久有效,直到被更改。

precison可以返回当前填充字符,setprecision不能。

设置显示的数制

指定数制显式输出数据,永久有效直到被修改。

int main()
{
	//	控制输出宽度
	cout << "1234567890" << endl;
	//	使用流控制符输出宽度
	cout << setw(6) << 4.5 << endl;
	cout << 4.5 << endl;
	cout << setw(5) << 4.5 << endl;

	//	使用width成员函数控制输出宽度
	const char* c1[3] = { "abc", "abcde", "abcdefgh" };
	for (int i = 0; i < 3; i++)
	{
		cout.width(6); //调用后生效一次
		cout << c1[i] << endl;
	}

	//	设置填充字符
	cout << endl  << "1234567890" << endl;
	//	使用流控制符填充字符
	cout << setfill('*');
	for (int i = 0; i < 3; i++)
	{
		cout.width(10); 
		cout << c1[i] << endl;
	}
	//	fill可以返回当前填充字符,本例中返回*
	char c2 = cout.fill('#');
	for (int i = 0; i < 3; i++)
	{
		cout.width(10); 
		cout << c1[i] << endl;
	}
	//	恢复fill设置填充字符之前的填充字符
	cout.fill(c2);
	for (int i = 0; i < 3; i++)
	{
		cout.width(10);
		cout << c1[i] << endl;
	}

	//	控制输出精度
	double PI = 3.141592653;
	cout << PI << endl;

	//	流控制符控制精度
	cout << setprecision(10) << PI << endl;;

	//	方法控制精度
	int op = cout.precision(4); // precision方法可以返回当前精度
	cout << PI << endl;
	cout.precision(op);
	cout << PI << endl;

	// 控制符hex,oct,dec控制显式不同的进制
	int n = 100;
	cout << "十进制" << n << endl;
	cout << "十六进制" << hex << n << endl;	
	cout << "八进制" << oct << n << endl;
	cout << "十进制" << dec <<  n << endl;
	return 0;
}

文件读写

读写文件的一般过程,打开文件,读/写文件,关闭文件。

打开文件

定义流对象并打开文件的两种方法

用默认构造函数创建对象,然后调用open方法打开文件。

使用有参构造函数,定义对象同时打开文件。

文件的打开方式

写入文件

<< ,插入运算符。

put方法,写入一个字符。

write方法,写入字符数组,还可以用于整体输出自定类型的数据。

int main()
{
	// 用默认构造函数创建对象,然后调用open方法打开文件
	ofstream myOut;
	myOut.open("D:\\test.txt");

	//	写入数据
	myOut << "Hello";
	myOut.put(' ').write("ios", 3).put('\n');
	
	//	关闭输出流
	myOut.close();

	//	使用有参构造函数
	ofstream myOut1("D:\\test.txt", ios_base::app);

	myOut1 << "Hello Student!" << endl;
	
	myOut1.close();

	return 0;
}

读取文件

>> ,提取运算符。

get方法,读取一个字符。

getline方法,读取一行字符。

read,读取字符数组,还可以用于整体读取自定义类型的数据。

#include <iostream>
#include <fstream>	//	读写文件都要导入fstream

using namespace std;

int main()
{
	char c[10], c1;
	int n;
	ifstream myIn("D:\\data.txt");
	//	读取字符串
	myIn >> c;
	cout << "c: " << c << endl;

	//	读取数字1, n是整型
	myIn >> n;
	cout << "n: " << n << endl;

	/*
		读取字符'1', c1是字符型
		myIn >> c1;
		cout << "c1: " << c1 << endl;
	*/

	//	提取字符串abcde
	myIn >> c;
	cout << "c: " << c << endl;
	//	读取空格。get不会忽略空格和换行符。
	myIn.get(c1);

	/*
		读取f。提取运算符会忽略空格和换行符。
		myIn >> c1;		
	*/
	cout << "c1: " << c1 << endl;

	myIn.getline(c, 10);
	cout << "c: " << c << endl;

	myIn.close();
	return 0;
}

读写二进制文件

#include <iostream>
#include <fstream>

using namespace std;

class MyClass
{
private:
	int length;
	int width;

public:
	MyClass(int length, int width)
	{
		this->length = length;
		this->width = width;
	}
	void show()
	{
		cout << length << ", " << width << endl;
	}
};

int main()
{
	MyClass mc1(10, 10), mc2(20, 20);
	mc1.show();
	mc2.show();

	//	把mc1的属性值以二进制形式写入文件test1.txt
	ofstream myOut("D:\\test1.txt", ios_base::binary | ios_base::out);
	/*
		write函数的参数时字符指针,要写入数据的长度
		(char*)&mc1 强制转换mc1的地址为字符指针;
		sizeof(mc1)获取mc1的数据占用的内存空间的大小。
	*/
	myOut.write((char*)&mc1, sizeof(mc1));	
	myOut.close();

	//	从test1.txt中读取二进制数到mc2中
	ifstream myIn("D:\\test1.txt", ios_base::binary | ios_base::in);
	myIn.read((char*)&mc2, sizeof(mc2));
	myIn.close();

	mc2.show();

	return 0;
}

文件读写位置指针

与ofstream对应的是写位置指针,指定下一次写数据的位置

seekp函数,移动写指针,p是put的缩写。

tellp函数,返回写指针的位置。

与ifstream对应的是读位置指针,执行下一次读数据的位置

seekg函数,移动读指针,g是get的缩写。

tellg,返回读指针位置。

seekg(n),n >0移动到文件的第n个字节后,n = 0移动到文件的起始位置。

seekg(n, ios::beg),从文件起始位置向后移动n个字节,n是大于或等于0的整数。

seekg(n, ios::end),从文件结尾位置向前移动n个字节,n是小于或等与0的整数。

seekg(n, ios::cur),从文件当前位置向前或后移动n个字节,整数和负数移动顺序相反。

streampos, tellg的返回值类型,表示文件位置,可以看成整型数据。

#include <iostream>
#include <fstream>

using namespace std;

class MyClass
{
private:
	int length;
	int width;

public:
	MyClass(int length, int width)
	{
		this->length = length;
		this->width = width;
	}
	void show()
	{
		cout << length << ", " << width << endl;
	}
};

int main()
{
	MyClass mc1(10, 10), mc2(20, 20), mc3(30,30);
	mc1.show();
	mc2.show();
	mc3.show();
	
	ofstream myOut("D:\\test1.txt", ios_base::binary | ios_base::out);	
	myOut.write((char*)&mc1, sizeof(mc1));
	myOut.write((char*)&mc2, sizeof(mc2));
	myOut.close();
	
	ifstream myIn("D:\\test1.txt", ios_base::binary | ios_base::in);
	myIn.seekg(sizeof(MyClass));
	myIn.read((char*)&mc3, sizeof(mc3));
	myIn.close();

	mc3.show();

	return 0;
}

错误处理函数

错误处理函数的主要作用是得到流对象当前的状态。

eof(),如果输入流结束,到文件尾,则返回true。

bad(),如果出现严重错误,不可恢复的错误,则返回true。

fail(),如果某种操作失败,则返回true。

good(),以上三种错误均未发生,则返回true。表示流对象状态正常。

clear(),清除所有错误状态。

#include <iostream>
#include <fstream>
using namespace std;

int main()
{
	int n;
	char c;

	cin >> n;
	cout << "n: " << n << endl;
	cout << "cin.good(): " << cin.good() << " cin.bad(): " << cin.bad() << " cin.fail(): " << cin.fail() << endl;
	
	//	清除错误状态奇
	cin.clear();	
	cout << "cin.good(): " << cin.good() << " cin.bad(): " << cin.bad() << " cin.fail(): " << cin.fail() << endl;

	cin >> c;
	cout << "c: " << c << endl;

	//	eof()判断文件是否读完了	
	ifstream myIn("D:\\test.txt");
	while (!myIn.eof())
	{
		myIn.get(c);
		cout << c ;
	}

	myIn.close();

	return 0;
}

输入输出文件流

fstream 同时具有输入和输出的功能。

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
	fstream myInOut("D:\\d.txt", ios::in | ios::out);

	//	定位读指针到文件末尾
	myInOut.seekg(0, ios::end);
	cout << "myInOut.tellg(): " << myInOut.tellg() << " myInOut.tellp(): " << myInOut.tellp() << endl;
	
	//	获取文件长度
	streampos len = myInOut.tellg();
	cout << "len: " << len << endl;
	
	//	动态分配空间用于存储文件内容
	char* data = new char[len];

	//	移动读指针到文件开头位置
	myInOut.seekg(0, ios::beg);	
	myInOut.read(data, len);

	//	移动写指针到文件末尾
	myInOut.seekp(0, ios::end);
	//	写入文件
	myInOut.write(data, len);
	
	delete[]data;
	myInOut.close();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值