目录
[C++ IO流](#C++ IO流)
流
数据从一个地方流向另外一个地方,
C++ IO流
i o stream 是对应输入输出终端流动的,f stream 是文件层面上流动,s stream 是内存层面上流动
内置类型能直接用流插入和流提取是因为库里面写好了函数重载
类型转换重载
多组输入
cpp
int main()
{
string s1;
while (cin >> s1)
{
cout << s1 << endl;
}
return 0;
}
cin >> s1 的返回值是cin的引用,为什么它可以作为逻辑判断?
因为构造函数可以支持没有关联的类型的转换,比如内置类型转自定义类型,
cpp
class C
{
public:
C(int x)
{}
};
int main()
{
C c1 = 1;
string s1 = "xxx";
return 0;
}
自定义也可以转自定义,只需要构造函数支持
cpp
class C
{
public:
C(int x)
{}
};
class D
{
public:
D(const C& c1)
{}
};
int main()
{
C c1 = 1;
D d1 = c1;
return 0;
}
自定义转内置
这时候要重载类型转换,比如转成int
cpp
class E
{
public:
operator int()
{
//...
return 9;
}
};
所以这里ios类进行了类型重载
与C的IO流同步
默认情况下,C和C++是各自读自己的缓冲区的,
这个接口默认是true开启的,如果你给false就是关掉,
文件IO流
C语言:
fgetc, fputc 针对单个字符的
fread, fwrite 针对字符串或一段内存
fscanf, fprintf, 针对进行格式化的
C++:
ifstream是读,接口:get, read, >>
ofstream是写, 接口:put, write, <<
这两个是类,里面都有对应操作的接口
把一个结构体写到文件然后读出来
有两种方法,二进制读写,文本读写
内存中整型都是4个字节,存的是补码,浮点数是存精度有对应的规则,硬盘就是字节流,
二进制读写
二进制写
内存写到硬盘,直接写过去,
写是ofstream类,文件可以显示打开和关闭,提供了open和close接口,也可以直接用构造函数打开,对象销毁会自动关闭,
写的话用write接口
cpp
class BinIO
{
public:
BinIO(const char* filename = "info.bin")
:_filename(filename)
{}
void Write(const ServerInfo& info)
{
//打开文件,二进制写
ofstream ofs(_filename, ofstream::out | ofstream::binary);
//写到文件,有多大写多大
ofs.write((char*)&info, sizeof(info));
}
private:
string _filename;
};
int main()
{
ServerInfo info = { "xxxxx", 123};
BinIO bin;
bin.Write(info);
return 0;
}
二进制读
cpp
void Read(ServerInfo& info)
{
ifstream ifs(_filename, ifstream::in | ifstream::binary);
ifs.read((char*)&info, sizeof(info));
}
cpp
int main()
{
ServerInfo info;
BinIO bin;
bin.Read(info);
return 0;
}
二进制读写方便但打开看不了
这里改成string会异常,因为string对象有自己的成员,成员指向字符串内容,二进制写会把成员直接写进去而不是字符串内容
同一个进程读写会导致浅拷贝,不同进程读写会导致野指针,二进制读写不适合容器,遇到指针要小心
文本读写
任何类型都要转成字符串才能往外写,利用to_string转字符串,
C语言把double转为字符串可以用sprintf, C++就用to_string
写
流插入到文件然后用换行分隔,内置类型的流插入库已经实现,自定义类型的流插入就去调用自定义自己的重载
cpp
void Write(const ServerInfo& info)
{
ofstream ofs(_filename);
ofs << info._address << endl;
ofs << info._x << endl;
ofs << info._date << endl;
}
读
不需要再单独处理换行了,因为流里面有一个规则,默认空格或换行就是分隔,想自己定义分隔符可以用getline
cpp
void Read(ServerInfo& info)
{
ifstream ifs(_filename);
ifs >> info._address;
ifs >> info._x;
ifs >> info._date;
}
字符串流stringstream
C语言,printf的内容到控制台,fprintf的内容就到文件里面, sprintf的内容从内存到内存
cpp
int main()
{
char sql[128];
char name[10];
scanf("%s", name);
sprintf(sql, "xxx");
sprintf(sql, "123123'%s'", name);
return 0;
}
C++,自定义类型会去调用自己的流重载
cpp
int main()
{
Date d(123, 123, 123);
ostringstream oss;
oss << d;
string sql3;
sql3 += "xxx = ";
sql3 += "'";
sql3 += oss.str();
sql3 += "'";
//也可以这样
ostringstream sql;
sql << "xxx = " << "'" << d << "'";
return 0;
}
把各种信息转化成字符串就序列化,反过来就是反序列化
stringstream包含了读和写