c++io流操作

流的概念

流就是若干字节组成字节序列,流操作从一个到另一个移动的过程

流中的内容:二进制数据 ASCII码

流类体系

C++中用类实现所有流类操作

  • 标准的输入输出流

    • C++格式控制

  • 字符流

  • 文件流

#include 	 //istream ostream
#include    //ifstream ofstream
#include  //istringstream  ostringstream
//注释是前面头文件的子类
using namespace std;
int main() 
{
	fstream out; 文件操作流(可读可写)
	ifstream iin; 文件操作流(只可读)
	return 0;
}

 

标准输入输出流

  • 重定向: C语言 freopen函数介绍

对象 类型 作用
cin 标准输入 从键盘读取,可以重定向
cout 标准输出 输出到控制台,可以重定向
cerr 标准错误输出 输出到控制台,不可以重定向
clog 标准错误输出 输出到控制台,可重定向
#include 
using namespace std;
int main() 
{
	cout << "标准输出" << endl;
	cerr << "标准错误" << endl;
	clog << "标准错误" << endl;
	return 0;
}

 三种标准输出作用是一样的,只是起不同的说明作用

字符和字符串输入

  • cout成员函数

    • put() : 输出一个字符

    • write(): 输出字符串

  • cin成员函数

    • get():输入一个字符

    • getline: 输入一个字符串

#include 
using namespace std;
int main() 
{

	cout << "标准输出" << endl;
	cerr << "标准错误" << endl;
	clog << "标准错误" << endl;

	//字符输入
	cout << "字符输入:" << endl;
	int userKey = cin.get();   //相当于c语言的getchar() 
	cout.put(userKey);         //相当于c语言的puts()

	char str[10] = { "" };
	cout << "字符串输入:" << endl;
	while (getchar() != '\n');
	cin.getline(str, 10);  //10个长度包含\0
	cout << str << endl;
	cout.write(str, 10);
    //cin.getline规定的长度n,少输入无所谓,多输入则只会截取n-1个可见字符(还有一个是尾零)
    //cout.write规定的长度n,无论字符串保存了多长的长度,只会输出n-1个可见字符(还有一个是尾零)
	return 0;
}

 

C++格式控制

  • 包含头文件: iomanip

  • 通过对象的形式,一种通过成员的函数形式

对象形式 实际含义
setbase(n) 设置多少进制输出整数(参数是8和16)
setw(n) 设置输出数据宽度(默认对齐是右对齐,不足补空格)
setiosflags(ios::left) 设置对齐方式: ios::left ,ios::right
setprecition(n) 单纯使用是控制有效位数,如果控制小数位数结合fixed
setfill(n) 填充字符

 

    //进制输出
	cout << setbase(16) << 32 << endl;
	cout << setbase(8) << 32 << endl;
	cout <

 

//默认右对齐
	cout << setw(10) << "姓名" << setw(10) << "年龄" << setw(10) << "编号" << endl;
	cout << setw(10) << "小芳" << setw(10) << 17 << setw(10) << 119911 << endl;

	cout << setiosflags(ios::left);  //设置左对齐
	cout << setw(10) << "姓名" << setw(10) << "年龄" << setw(10) << "编号" << endl;
	cout << setw(10) << "小芳" << setw(10) << 17 << setw(10) << 119911 << endl;

                c++io流操作_第1张图片

 

	cout << setprecision(4) << 300.12345 << endl;  //直接用控制的是有效位数
	cout << fixed << setprecision(4) << 300.12349 << endl;  //小数位数

                           c++io流操作_第2张图片

 

字符流

  • 包含头文件: sstream

    • istringstream

    • ostringstream

    • stringstream

  • 一般处理字符流的时候用的是stringstream类型的对象

  • 获取字符流中的stirng

    • string str(); //获取string

    • void str(const string& str) //重置流对象中字符串

  • 字符流做什么

    • 数据类型的转换

    • 数据的分割

	stringstream stream("ILoveyou");
	cout << stream.str() << endl;  //不可直接cout(cout<> str;   //将stream中的字符流入str中
	cout << str << endl;
	stream.str("");		  //清除

字符流还可以做数据转换,字符串转整数或者整数转字符串

	//数据类型转换
	//整数转字符串,字符串转数字
	string num = to_string(123);  //string自带的将整数转为字符串
	cout << num << endl;

	int inumber = 12123;
	char result[20] = { "" };
	stringstream buf(result);  //开辟一个空间大小和result一样
	buf << inumber;    //将inumber的整型数字流入buf中
	buf >> result;     //再将buf中的字符串流出到result中
	cout << result << endl;  //就可以做到数据类型转换

	//字符串转换成整型有溢出错误,需要自己手动处理
	stringstream strNum("12345435");
	int dataNum = 0;
	strNum >> dataNum;
	cout << dataNum << endl;

 当我了解到这种字符串与整型之间相互转换的时候,突然想到了leetcode的一题,然后拿着试一试的想法去做做看,没想到还真的可以AC

c++io流操作_第3张图片

 

字符流还可以做数据切割 

	//数据切割(流中默认空格作为单一数据的间隔)
	stringstream ip("ip: 192.168.1.1");
	char strip[20] = { "" };
	ip >> strip;		//ip: 拿出来

	int ipNum[4];       //存IP地址的四组整型数据
	char userKey;       //存整型数据之间的符号"."
	ip >> ipNum[0];
	ip >> userKey;

	ip >> ipNum[1];
	ip >> userKey;

	ip >> ipNum[2];
	ip >> userKey;

	ip >> ipNum[3];
	for (int i = 0; i < 4; i++)
	{
		cout << ipNum[i] << "\t";  //打印结果
	}

 还需要注意一点,流在做二次或多次转换的时候,必须调用clear清除处理 因为如果不做清除,会导致字符流中的数据有错误,无法将数据正常流出来

 

文件操作流

  • 包含头文件: fstream

    • ofstream: 打开文件只能写操作

    • ifstream: 打开文件只读操作

    • 一般大家创建一个fstream对象,可读可写

  • 打开文件

    • 构造的方式,带参数构造函数:const char* URL,ios::openmode mode(URL是文件名字,ios::openmode是打开文件方式)

    • 成员函数方式: void open(const char* URL,ios::openmode mode)

    • 判断文件打开是否成功

      • !is_open()函数判断是否打开成功 ,!is_open()是1的打开失败

      • !文件对象 .!对象是1打开失败

读写方式 作用
ios::in 读的方式打开文件(相当于c语言的r)
ios::out 写的方式打开文件(相当于c语言的w)
ios::app 追加写文件(相当于c语言的a)
ios::ate 打开已有文件,指针在文件末位
ios::trunc 文件不存在具有创建方式
ios::binary 二进制打开,默认打开方式ASCII码
ios::nocreate 不创建
ios::noreplace 不替换

 组合方式: 用位或, 可读可写: ios::in|ios::out

  • 关闭文件

    • close关闭文件

  • 文件读写

    • 直接采用>> <<符号进行读写

    • 采用成员函数读写:read函数和write成员函数

  • 文件指针移动

    • ifstream文件指针

      • ifstream& seekg(long int pos);

      • ifstream& seekg(long int pos,ios_base::seekdir begin);

    • ofstream文件指针

      • ofstream& seekp(long int pos);

      • ofstream& seekp(long int pos,ios_base::seekdir begin);

    • begin:

      • ios::beg 开始位置

      • ios::cur 当前位置

      • ios::end 结束位置

 

	//打开文件测试
	//fstream file("xxoo.txt",ios::in|ios::out|ios::trunc);
	//等效下面两行
	fstream file;
	file.open("xxoo.txt", ios::in | ios::out | ios::trunc);
	if (!file || !file.is_open())
	{
		cerr << "文件打开失败" << endl;
	}
	file.close();
class MM
{
public:
	MM() {}
	MM(string name, int age, int num) :name(name), age(age), num(num) {}
	void print()
	{
		cout << name << "\t" << age << "\t" << num << endl;
	}
	//采用>>  <<
	void saveFile(string fileName)
	{
		fstream file(fileName, ios::in | ios::out | ios::app);
		if (!file)
		{
			cout << "打开文件失败!" << endl;
			return;
		}
		file << name << " " << age << " " << num << endl;  //直接将数据流入文件中
		file.close();
	}
	void readFile(string fileName)
	{
		fstream file(fileName, ios::in);
		if (!file)
		{
			cout << "打开文件失败!" << endl;
			return;
		}
		while (true)   //循环的方式将文件的所有数据全部读出来
		{
			MM temp;
			file >> temp.name >> temp.age >> temp.num;
			if (file.eof())   //注意退出循环的判断写在这,不然会出错
			{
				break;
			}
			temp.print();
		}
		file.close();
	}
protected:
	string name;
	int age;
	int num;
};
int main()
{
	MM mm("xxx", 18, 1001);
	mm.saveFile("mm.txt");
	mm.readFile("mm.txt");
	return 0;
}

c++io流操作_第4张图片

 

 

 

接下来我们使用ASCII码的方式读取文件操作,测试为将文件一的内容读取出来,保存到文件二中

c++io流操作_第5张图片

void asciiRWFile(string readFile, string writeFile)
{
	//流的方式
	//字符或者字符串的
	fstream read(readFile, ios::in);
	fstream write(writeFile, ios::out);
	while (!read.eof())
	{
		char userkey = read.get();   //getline()
		write.put(userkey);			 //write()函数
                                     //也可以用字符串的方式读取
	}
	read.close();
	write.close();
}
int main()
{
	asciiRWFile("文件1.txt", "文件2.txt");
	return 0;
}

c++io流操作_第6张图片

 如果是中文的话,建议用字符串的方式读取,如果用字符读取可能会出错(我就出现了乱码)

用法和cin.getline与cout.write一样

 

 接下来是二进制读取文件

二进制读取文件涉及到一个文件指针的移动去计算该文件的字节数,我们先来讲读取方式 

//二进制读写
void binaryRWFile(string readFile, string writeFile)
{
	fstream r(readFile, ios::in | ios::binary);
	fstream w(writeFile, ios::out | ios::binary);
	while (!r.eof())      //这里二进制读取的判断条件要放在while中,与上面的讲的直接用流操作符来读取文件加以区分
	{
		char str[1024] = { "" };  //缓冲区 开辟一个大小为1024字节的空间
		r.read(str, 1024);
		w.write(str, strlen(str));  //长度写多少就写入文件多少
	}
	r.close();
	w.close();
}
int main()
{
	binaryRWFile("文件1.txt", "文件2.txt");
	return 0;
}

 接下来来讲一下文件指针移动,这样在二进制读写就可以准确判断文件的大小了,就不会浪费空间

//文件指针移动
int getSize(string fileName)
{
	fstream read(fileName, ios::in | ios::binary);  //用二进制的方式打开文件
	read.seekg(0, ios::end);  //seekg函数可以去百度查看参数作用,这里的含义是,
						      //使文件指针在文本末尾的位置移动零个字节,也就是文本末尾
	//这个偏移量可正可负,正是向后移动,负是向前移动
	int size = read.tellg();   //返回文本的长度
	read.close();
	return size;
}

c++io流操作_第7张图片

 

c++io流操作_第8张图片

 c++io流操作_第9张图片

 可以发现,我们的测量是准确的,这样就可以做到二进制读取文件了

你可能感兴趣的:(c/c++,c++,开发语言)