文件的读写
- >>
- <<
- get
- put
- read
- write
- 文本模式打开与二进制模式打开区别
>> 、<<
#include <iostream>
#include <fstream>
#include<cassert>
#include<string>
using namespace std;
int main(void)
{
ofstream fout("test.txt");
fout << "abc" << " " << 200;
fout.close();
ifstream fin("test.txt");
string s;
int n;
fin >> s >> n;
cout << s << " " << n << endl;
}
get、put
#include <iostream>
#include <fstream>
#include<cassert>
#include<string>
using namespace std;
int main(void)
{
ofstream fout("test2.txt");
char ch;
for (int i = 0; i < 26; i++)
{
ch = 'A' + i;
fout.put(ch);
}
fout.close();
ifstream fin("test2.txt");
while (fin.get(ch))
{
cout << ch;
}
cout << endl;
}
文件模式打开与二进制模式打开的区别
- 如果以文本的方式打开文件,写入字符的时候,遇到\n会做转换,写入\r不做转换
- windows平台\n转为 \r\n
- linux平台保留不变
- mac系统\n转为\r
- 如果以二进制的方式打开文件写入字符时,遇到\n不会做转换
- 以文本方式打开文件,也可以写入二进制数据;以二进制方式打开文件也可以写入文本
- 写入的数据是二进制还是文本,与打开方式无关,与写入使用的函数有关
- 要写二进制数据,应该用write,相应的读要用read
二进制文件的读写
- 二进制文件不同于文本文件,它可用于任何类型的文件(包括文本文件)
- 对二进制文件的读写可采取从istream类继承下来的成员函数read()和从ostream类继承下来的成员函数write()
- 文件打开操作时使用枚举常量ios::binary,例如
ofstream fout(“binary.dat”, ios::out | ios::binary);
write()成员函数
- 函数功能:以字节单位向文件流中写入整块数据,最有价值的应用可以处理结构体变量和类对象
- 函数原型:ostream& write(const char* pch, int nCount);
- 函数的参数:
- pch 写入的数据的指针
- nCount 写入数据的字节大小
read()成员函数
- 函数功能:从文件流中读出整块数据
- 函数原型:istream& read(const char* pch, int nCount);
- 函数的参数:
- pch 用来接收数据的指针
- nCount 读取字节数的大小
#include<iostream>
#include <fstream>
#include<string>
using namespace std;
struct Test
{
int a;
string b;
string c;
};
int main(void)
{
Test t1;
t1.a = 100;
t1.b = "xxxccccccccccccccccccccaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaawwwwwwwwwwwwwwwwwwwwww";
t1.c = "yyyeeeeeeeeeeeeeeeeeeeeebbbbbbbbbbbbbbbbbbbbbbbbbbbbbyyyyyyyyyyyyyyyyyyyyyyy";
cout << "sizeof(string) = "<<sizeof(string) << endl;
cout << "sizeof(Test) = "<<sizeof(Test) << endl;
cout << "sizeof(t1) = " <<sizeof(t1) << endl;
ofstream fout("test4.txt", ios::out | ios::binary);
fout.write(reinterpret_cast<char*>(&t1), sizeof(t1));
fout.close();
Test t2;
ifstream fin("test4.txt", ios::in | ios::binary);
fin.read(reinterpret_cast<char*>(&t2), sizeof(Test));
cout << t2.a << endl;
cout << t2.b << endl;
cout<< t2.c << endl;
fin.close();
return 0;
}
string和Test结构提的大小总是不变的,而字符串内容的大小在变,在写入和读取的时候就会出错!最好是要分开读取和写入!
#include<iostream>
#include <fstream>
#include<string>
using namespace std;
struct Test
{
int a;
string b;
string c;
};
int main(void)
{
Test t1;
t1.a = 100;
t1.b = "xxxccccccccccccccccccccaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaawwwwwwwwwwwwwwwwwwwwww";
t1.c = "yyyeeeeeeeeeeeeeeeeeeeeebbbbbbbbbbbbbbbbbbbbbbbbbbbbbyyyyyyyyyyyyyyyyyyyyyyy";
int len = 0;
ofstream fout("test4.txt", ios::out | ios::binary);
fout.write(reinterpret_cast<char*>(&t1.a), sizeof(int));
len = t1.b.length();
fout.write(reinterpret_cast<char*>(&len), sizeof(int));
fout.write(t1.b.data(), t1.b.length());
len = t1.c.length();
fout.write(reinterpret_cast<char*>(&len), sizeof(int));
fout.write(t1.c.data(), t1.c.length());
fout.close();
Test t2;
ifstream fin("test4.txt", ios::in | ios::binary);
fin.read(reinterpret_cast<char*>(&t2.a), sizeof(int));
fin.read(reinterpret_cast<char*>(&len), sizeof(int));
t2.b.resize(len);
fin.read(reinterpret_cast<char*>(&t2.b[0]), len);
fin.read(reinterpret_cast<char*>(&len), sizeof(int));
t2.c.resize(len);
fin.read(reinterpret_cast<char*>(&t2.c[0]), len);
cout << t2.a << endl;
cout << t2.b << endl;
cout<< t2.c << endl;
fin.close();
return 0;
}
当前文件流活动指针
- 文件流指针用以跟踪发生I/O操作的位置
- 每当从六中读取或写入一个字符,当前活动指针就会向前移动
- 当打开方式中不含有ios::ate或ios::app选项时,则文件指针被自动移到文件的开始位置,即字节地址为0的位置。
文件的随机读写
seekp和seekg
- 函数功能
- seekp: 设置输出文件流的文件流指针位置
- seekg: 设置输入文件流的文件流指针位置
- 函数原型
- ostream& seekp(streampos pos);
- ostream& seekp(streamoff off, ios::seek_dir dir);
- ostream& seekg(streampos pos);
- ostream& seekg(streamoff off, ios::seek_dir dir);
- 函数参数
- pos:新的文件流指针位置值
- off:需要偏移的值
- dir:搜索的起始位置
tellp和tellg
- 函数功能
- tellp: 获得输出的文件流指针的当前位置,以字节为单位
- tellg: 获得输入的文件流指针的当前位置,以字节为单位
- 函数原型
- streampos tellp();
- streampos tellg();
- 函数的返回值: 实际上是一个long类型
#include<iostream>
#include <fstream>
#include<string>
#include <cassert>
using namespace std;
int main(void)
{
ifstream fin("test5.txt");
assert(fin);
char ch;
fin.seekg(2);
fin.get(ch);
cout << ch << endl;
fin.seekg(-1, ios::end);
fin.get(ch);
cout << ch << endl;
fin.seekg(0, ios::end);
streampos pos = fin.tellg();
cout << pos << endl; //此方法可判断文件大小
return 0;
}
seek_dir
- dir参数用于文件流指针的定位操作上,代表搜索的起始位置
- 在ios中定义的枚举类型
enum seek_dir {beg, cur, end}; - 每个枚举变量的含义
- ios::beg:文件流的起始位置
- ios::cur :文件流的当前位置
- ios::end:文件流的结束位置