IO流
- 流:若干个字节组成的字节序列
- 设备 ->程序(stdin)
- 程序 ->设备(stdout)
- 程序 ->文件(文件流)
- 流管理体系:输入输出流,字符流,文件流
标准输入输出流
- 流对象的类型:运算符重载中
- 输入输出对象:
cin | cout | cerr | clog |
---|---|---|---|
标准输入 | 标准输出 | 标准错误 | 标准错误 |
可被重定向 | 可被传重定向 | 不可重定向 | 可重定向 |
- 流对象调用成员函数方式:字符和字符串输入方式
- get():输入字符
- put():打印字符
- getline():输入字符串
- write():打印字符串
#include <iostream>
#include <string>
int main()
{
std::clog << "clog" << std::endl;
std::cerr << "cerr" << std::endl;
//输入字符
char str = std::cin.get();
//打印字符
std::cout.put(str);
std::cout << std::endl;
//清空缓冲区,\n
while (std::cin.get() != '\n');
//输入字符串,可以带空格
char s[20]="";
std::cin.getline(s, 20);
std::cout << s << std::endl;
//打印字符串,可以控制打印数量
std::cout.write(s,8);
return 0;
}
- 运行结果
- 流控制字符:类似与C语言的格式控制字符
- 头文件包含:#include <iomanip>
- 流控制字符基本上都有一个成员函数的方式
- setbase:设置进制
- setprecision():设置有效位数
- 想要控制小数位,要结合fixed使用
- setiosflags(ios::mode):设置对齐方式
- ios::left
- ios::right
- setw():设置输出数据的宽度
- 时间格式:put_time 格式化时间
#include <iostream>
#include<iomanip>
int main()
{
//进制,无二进制打印方式
std::cout <<"打印十六进制的15:" << std::setbase(16) << 15 << std::endl;
std::cout << "打印十六进制的15:" << std::hex << 15 << std::endl;
std::cout << "打印八进制的15:" << std::setbase(8) << 15 << std::endl;
std::cout << "打印八进制的15:" << std::oct << 15 << std::endl;
//设置了进制后记得设置回十进制方式
std::cout << "打印十进制的15:" << std::setbase(10) << 15 << std::endl;
std::cout << "打印十进制的15:" << std::dec << 15 << std::endl << std::endl;
//精度控制,会默认四舍五入
std::cout <<"控制前4位有效位:" << std::setprecision(4) << 123.4567 << std::endl;
std::cout << "控制前4位小数有效位:" << std::fixed << std::setprecision(4) << 123.456789 << std::endl << std::endl;
//制表,默认是右对齐,加了设置对齐方式就是所设置的对齐方式
std::cout << "制表,默认是右对齐,加了设置对齐方式就是所设置的对齐方式" << std::endl;
std::cout << std::setw(8) << "小瓜"
<< std::setw(10) << 21
<< std::setw(16) << 210591025
<< std::endl;
std::cout << std::setw(8) << "小瓜"
<< std::setw(10) << 21
<< std::setw(16) << 210591025
<< std::endl << std::endl;
std::cout << "加了左对齐后:" << std::endl;
std::cout << std::setiosflags(std::ios::left)
<< std::setw(8) << "小瓜"
<< std::setw(6) << 21
<< std::setw(6) << 210591025
<< std::endl;
std::cout << std::setiosflags(std::ios::left)
<< std::setw(8) << "小瓜"
<< std::setw(6) << 21
<< std::setw(6) << 210591025
<< std::endl << std::endl;
//也可以调用成员函数的方式,基本上每个格式控制流都有一个成员函数例如;
//std::cout.width(6); 等效与setw()
//具体看官方手册有详细
//时间格式
time_t t = time(nullptr);
tm* tmData = localtime(&t);
std::cout << "当前日期时间:" << std::put_time(tmData, "%F %r") << std::endl;
return 0;
}
- 运行结果
文件流
- fstream类:可读可写
- ofstream:写操作
- ifstream:读操作
- 使用的时候包含父类:#include <fstream>
- 打开文件语法
void open(const char* url,ios::openmode mode);
ios::in 读
ios::out 写
ios::app 追加模式,有创建功能
ios::ate 打开已有文件,文件指针在文件末位
ios::trunc 文件不存在创建文件
ios::binary 二进制
ios::nocreate 不创建的文件方式
ios::replace 不做替换
- 组合方式用 | 例如:
- ios::in | ios::out
- ios::in | ios out | ios::binary
- 关闭文件:void close()
- 文件状态函数
- 文件是否为空
- bool is_open():返回false文件打开失败,true为成功
- 取反文件对象操作也可以
- 是否到达文件结束:int eof()
- 文件是否为空
void openFile()
{
std::fstream file;
//一般就in out trunc三个一起
file.open("xiaogua.txt", std::ios::in|std::ios::out|std::ios::trunc);
//!file和!file.is_open()任用一个就行
if (!file||!file.is_open())
{
std::cout << "打开文件失败" << std::endl;
}
else
{
//文件操作一定要使用后关闭文件
file.close();
}
}
- 读写文件
- 文件流对象结合>> <<完成读写
- 字符的方式读写
- get函数
- put函数
- 调用成员函数读写
- read:读操作
- write:写操作
#include <iostream>
#include <fstream>
#include <string>
//读写文件
class IOfile
{
public:
IOfile(std::string name = "", int age = 0, int id = 0) :name(name), age(age), id(id) {}
//文件保存操作
void sevaFile(const char* fileName)
{
std::fstream file(fileName, std::ios::in | std::ios::out | std::ios::trunc);
if (!file)
{
std::cout << "文件打开失败" << std::endl;
}
else
{
//写入文件操作尽量带空格和格式,方便读出,因为文件里面以空格为数据的结束
file << name << " " << age << " " << id << std::endl;
file.close();
}
}
//文件的读入操作
void readFile(const char* fileName)
{
std::fstream file(fileName, std::ios::in);
if (!file)
{
std::cout << "文件打开失败" << std::endl;
}
else
{
file >> this->name >> this->age >> this->id;
file.close();
}
}
void print()
{
std::cout << name << " " << age << " " << id << std::endl;
}
protected:
std::string name;
int age;
int id;
};
int main()
{
IOfile xiaogua("小瓜", 21, 10001);
xiaogua.sevaFile("xiaogua.txt");
IOfile test;
test.readFile("xiaogua.txt");
test.print();
return 0;
}
- 以字符或字符串的方式读写文件拷贝文件
#include <iostream>
#include <fstream>
#include <string>
//字符的方式读写文件拷贝文件
void copyFileByASCII(const char* readFile, const char* writeFile)
{
std::fstream r(readFile, std::ios::in);
std::fstream w(writeFile, std::ios::out);
if (!r || !w)
{
std::cout << "打开文件失败" << std::endl;
}
以字符的方式读写
//while (!r.eof())
//{
// char key = r.get();
// w.put(key);
//}
//r.close();
//w.close();
//以字符串的方式读写
char buf[1024] = "";
r.getline(buf, 1024);
//想写多少数据就写多长
w.write(buf, strlen(buf));
r.close();
w.close();
}
int main()
{
copyFileByASCII("xiaogua.txt", "dagua.txt");
return 0;
}
- 以二进制的方式读写拷贝文件
#include <iostream>
#include <fstream>
#include <string>
//字符的方式读写文件拷贝文件
void copyBinaryFile(const char* r, const char* w)
{
std::fstream rFile(r, std::ios::in | std::ios::binary);
std::fstream wFile(w, std::ios::out);
if (!rFile || !wFile)
{
std::cout << "文件打开失败!" << std::endl;
}
else
{
while (!rFile.eof())
{
char buf[5] = "";
//不能读满,读满不是一个字符串
rFile.read(buf, 4);
//写的长度就是实际长度,如果超出就会写空格进去
wFile.write(buf, strlen(buf));
}
wFile.close();
rFile.close();
}
}
int main()
{
copyBinaryFile("xiaogua.txt", "dashagua.txt");
return 0;
}
- 文件指针移动
- ifstream类对象
- ifstream& seekg(long int pos);
- ifstream& seekg(long int pos,ios::base::seekdir pos);
- ofstream类对象
- ofstream& seekg(long int pos);
- ofstream& seekg(long int pos,ios::base::seekdir pos);
- ios::base::seekdir
- ios::beg 开始位置
- ios::end 结束位置
- ios::cur 当前位置
- ifstream类对象
#include <iostream>
#include <fstream>
#include <string>
//文件指针移动
void seekFile(const char* fileName)
{
std::fstream r(fileName, std::ios::in);
if (!r)
{
std::cout << "文件打开失败!" << std::endl;
}
else
{
//寻找6这个位置的数据
r.seekg(6);
std::cout << (char)r.get() << std::endl;
//寻找倒数第二个位置数据
r.seekg(-2, std::ios::end);
std::cout << (char)r.get() << std::endl;
r.close();
}
}
int main()
{
seekFile("xiaogua.txt");
return 0;
}
字符流
- 字符流头文件:sstream
- istringstream
- ostringstream
- 一般使用stringstream类
- string str():获取字符流对象中的字符串
- void str(const string& str):重置字符流对象中的字符串
#include <iostream>
#include <sstream>
int main()
{
std::stringstream str;
str << "xiaogua";
char buf[1024] = "";
str >> buf;
std::cout << buf << std::endl;
std::cout << str.str() << std::endl;
char temp[1024] = "dagua";
str.str(temp);
std::cout << str.str() << std::endl;
return 0;
}
-
运行结果
-
一般使用场景:
- 字符串切割
- 数据的类型转换
#include <iostream>
#include <sstream>
struct Date
{
int year;
int month;
int day;
};
int main()
{
//数字转字符串
int num = 123;
std::cout << std::to_string(num) << std::endl;
//字符串转数字,一个字符流多次做类型转换时,一定记得clear清除
std::stringstream temp;
std::string str = "123";
int result = 0;
temp << str;
temp >> result;
std::cout << result << std::endl;
//做数据分割
std::stringstream info("2023 年 8 月 1 日");
struct Date date;
std::string value;
info >> date.year;
info >> value;
info >> date.month;
info >> value;
info >> date.day;
info >> value;
std::cout << date.year << " " << date.month << " " << date.day << std::endl;
std::cout << info.str() << std::endl;
return 0;
}
- 运行结果