C++进阶学习---IO流

IO流

C++兼容C,所以C中的输入输出函数依然可以在C++中使用,但是直接把C的那套输入输出搬到C++中肯定无法满足C++的需求。

使用cout进行输出

cout格式化

格式设置完成之后将以对应格式打印,直到格式状态设置为其他的选项为止

cout<<showbase;					//设置显示进制前缀
cout << dec << "dec:" << 15 << endl;
cout << oct << "oct:" << 15 << endl;
cout << hex <<"hex:"<< 15 << endl;

另外一种对象设置的方法,了解即可,没上边的方便

cout.setf(ios::showbase); 		//设置显示进制前缀
cout << "dec" << 15 << endl; 	//默认10进制
cout.unsetf(ios::dec);    		//取消10进制	一定要取消
cout.setf(ios::hex);   			//设置16进制
cout << "hex:" << 15 << endl;
调整字节宽度以及填充字符

头文件:

#include <iomanip>
const char* str = "sirius";
cout.width(10);		//设置宽度
cout << str << endl;
cout.width(10);		//设置宽度
cout.fill('*');		//设置填充字符
cout << str << endl;
cout.precision(2);	//设置精度
cout << 3.1415 << endl;
输出结果:
    sirius
****sirius
3.1
setf()相关
常量含义
ios_base::boolalpha输入输出bool值,可以为ture或false
ios_base::showbase显示前缀0x01
ios_base::showpoint显示末尾的小数点
ios_base::showpos在正数前加+
参数含义
ios_base::fixed(默认)使用定点计数法
ios_base::scientific使用科学计数法
ios_base::left使用左对齐
ios_base::right(默认)使用右对齐
ios_base::internal符号或者基数前缀左对齐,值右对齐
字符串流

头文件

#include <sstream>
#include <iostream>
#include <sstream>
using namespace std;
int main() {
	//类型转换
	string res = "100";
	int num = 0;
	stringstream ss;
	ss << res;
	ss >> num;
	cout << num << endl;

	//分割字符串+类型转换
	string ip = "192.168.0.1";
	stringstream ss1(ip);
	int a1, a2, a3, a4;
	char ch;
	ss1 >> a1 >> ch >> a2 >> ch >> a3 >> ch >> a4;
	cout << a1 << " " << a2 << " " << a3 << " " << a4 << " " << ch << endl;

	//拼接字符串
	stringstream ss2;
	num = 3;
	char str[] = "14159";
	ss2 << num << ch << str;
	cout << ss2.str() << endl;
	return 0;
}
输出:
100
192 168 0 1 .
3.14159

文件流

头文件:

#include<fstream>

文件流常用函数

函数名描述
open打开文件
is_open文件是否被打开
close关闭文件
getline读取一行
read输入(读)到对象
write输出(写)到文件
flush将缓冲区的数据写出到文件,再清空它
tellg输入(读)文件指针位置
tellp输出(写)文件指针位置
seekg设置输入(读)文件指针位置
seekp设置输出(写)文件指针位置
eof是否到了流尾部

**C++ **和 C的文件打开模式

**C++**模式C模式描述
ios_base::in“r”打开以读取
ios_base::out“w”等价于ios_base::out | ios_base::trunc
ios_base::out | ios_base::trunc“w”打开以写入,如果已存在,则截断文件
ios_base::out | ios_base::app“a”打开以写入,只追加
ios_base::out | ios_base::in“r+”打开以读写,在文件允许的位置写入
ios_base::out | ios_base::in | ios_base::trunc“w+”打开以读写,如果已存在,则截断文件
ios_base::binary“b”以二进制的形式打开

截断文件:在文件写入之前擦除掉所有数据

open第三个参数

模式描述
_SH_DENYRW拒绝读写
_SH_DENYWR拒绝写
_SH_DENYRD拒绝读
_SH_DENYNO可读写
_SH_SECURE安全模式,向前兼容

示例程序:

#include<iostream>
#include<fstream>
using namespace std;
struct Student
{
	char name[20];
	int num;
	int age;
	char gender;
};
int main()
{
	fstream inFile;
	ofstream outFile;
	Student stu[3] = { {"张三",1001,18,'M'},{ "李四",1002,18,'M' } ,{ "王二",1003,18,'M' } },temp;

	outFile.open("test.txt", ios_base::out);   
	inFile.open("test.txt", ios_base::in);
	if (!outFile) {
		cerr << "open error!" << endl;
		abort();
	}
	if (!inFile) {
		cerr << "write error!" << endl;
		abort();
	}

	for (int i = 0; i < 3; i++)
	{
		outFile.write((char*)&stu[i], sizeof(Student));
		//outFile << "\n";	//插入换行符
	}
	outFile.close();
	for (int i = 0; i < 3; i++)
	{
		inFile.read((char*)&temp, sizeof(Student));
		cout << temp.age << temp.gender << temp.name << temp.num << endl;
	}
	inFile.close();
	cin.get();
	return 0;
}

打包解包

要想将文件打包生成文件,我们需要一张索引表,索引表里面包括关于文件的信息,例如文件名,文件大小…

索引表之后就是文件内容,假设我有四张图片,需要将四张图片打包生成一个.pack包,并且pack包能够被解开获取里面的内容

首先看一下索引表有什么内容

首先是红色区域,占8个字节,存储索引表的信息,索引表的左边是索引表的大小,右边是文件数量

其次是索引表中包含的文件信息,从左到右依次是文件名大小、文件偏移量,文件大小,文件名

文件偏移量:就是资源文件在打包文件中的位置

在这里插入图片描述

然后开始关于C++文件操作的打包解包:

#include<iostream>
using namespace std;
#include <fstream>
//索引表大小:4  文件数量:4   文件1大小 文件1偏移  文件1名大小 文件1名  文件2.。。
struct FileInfo
{
	int fileNameSize;	//文件名字大小
	int fileOffset;		//文件的偏移量
	int fileSize;		//文件的大小
	char fileName[20];	//文件名
};
void packFile()
{
	FileInfo fileList[4] = {
		{ 0,0,0,"1.jpg" },
		{ 0,0,0,"2.jpg" },
		{ 0,0,0,"3.jpg" },
		{ 0,0,0,"4.jpg" }
	};
	fstream file[4];

	int listSize = 0;	//索引表大小
	int fileNum = 4;	//文件数量
	for (int i = 0; i < 4; i++)
	{
		fileList[i].fileNameSize = strlen(fileList[i].fileName) + 1;	//1是\0
		listSize += fileList[i].fileNameSize + 12;	//求索引表的大小

		file[i].open(fileList[i].fileName, ios_base::in | ios_base::binary);	//打开文件
		file[i].seekp(0, ios_base::end);					//读指针移动到末尾
		fileList[i].fileSize = file[i].tellp();				//获取文件大小
		file[i].seekp(0, ios_base::beg);					//读指针移动到开头
	}
	//写文件索引信息
	fstream outfile("new.pack", ios_base::out | ios_base::binary);
	outfile.write((char*)&listSize, 4);
	outfile.write((char*)&fileNum, 4);
	//写索引表
	for (int i = 0; i < 4; i++)
	{
		if (i == 0)
			fileList[i].fileOffset = 8 + listSize;
		else
			fileList[i].fileOffset = fileList[i - 1].fileOffset + fileList[i - 1].fileSize;

		outfile.write((char*)&fileList[i].fileNameSize, 4);
		outfile.write((char*)&fileList[i].fileOffset, 4);
		outfile.write((char*)&fileList[i].fileSize, 4);
		outfile.write((char*)&fileList[i].fileName, fileList[i].fileNameSize);
	}
	//写文件
	char ch;
	for (int i = 0; i < 4; i++)
	{
		while (ch = file[i].get(),!file[i].eof())
		{
			outfile.put(ch);
		}
		file[i].close();
	}
	outfile.close();
}
void unPackFile() 
{
	fstream inFile;
	inFile.open("new.pack", ios_base::in | ios_base::binary);
	int listSize;	//索引表大小
	int fileNum;	//文件数量
	//读文件索引信息
	inFile.read((char*)&listSize, 4);
	inFile.read((char*)&fileNum, 4);

	FileInfo* fileList = new FileInfo[fileNum];
	fstream *file = new fstream[fileNum];
	//读索引表
	for (int i = 0; i < fileNum; i++)
	{
		inFile.read((char*)&fileList[i].fileNameSize, 4);
		inFile.read((char*)&fileList[i].fileOffset, 4);
		inFile.read((char*)&fileList[i].fileSize, 4);
		inFile.read((char*)&fileList[i].fileName, fileList[i].fileNameSize);
		file[i].open(fileList[i].fileName, ios_base::out|ios_base::binary);
	}
	
	for (int i = 0; i < fileNum; i++)
	{
		for (int j = 0; j < fileList[i].fileSize; j++)
		{
			file[i].put(inFile.get());
		}
		file[i].close();
	}
	inFile.close();
	delete[] fileList;
	delete[] file;
}
int main()
{
	packFile();
	//unPackFile();
	return 0;
}

需要注意的是怎么写入的怎么读取

fstream outfile("new.pack", ios_base::out | ios_base::binary);//二进制写入
inFile.open("new.pack", ios_base::in | ios_base::binary);	  //二进制读取

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DeRoy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值