文件的输入输出流详解
文本文件的写操作
C++中文件打开方式
C++中的文件的打开方式 |
解释 |
Ios::in |
以只读方式打开文件 |
Ios::out |
以写文件的方式打开文件 |
Ios::ate(at the end的简写) |
文件的初始操作位置:文件尾部 |
Ios::app(append的简写,相当于ios::in+ios::ate) |
在文件尾部写文件 |
Ios::trunc(truncate的简写)
扫描二维码关注公众号,回复:
12282238 查看本文章
|
清除文件内容 |
Ios::binary |
以二进制的方式操作文件 |
C++中文件打开方式与C语言文件打开方式的对应关系
C++文件打开方式 |
C语言文件打开方式 |
解释 |
Ios::in |
r |
只读方式打开文件 |
Ios::out |
w |
只写方式打开文件 |
Ios::app+ios::in |
a |
追加方式打开只写文件 |
Ios::in+ios::out |
+ |
可读可写 |
Ios::binary |
b |
以二进制方式打开文件 |
无(默认文件打开方式) |
t |
以文本方式打开文件(默认方式下以文本方式打开文件) |
Ios::in+ios::out |
r+ |
以可读可写的方式打开文件 |
Ios::in+ios::out+ios::binary |
rb+ |
以可读可写、二进制方式打开文件 |
Ios::in+ios::out |
rt+ |
以可读可写、文本方式打开文件 |
Ios::app+ios::in+ios::out |
a+ |
以追加、可读写的方式打开文件 |
Ios::in+ios::out |
w+ |
以读写的方式打开文件 |
文本文件写操作的步骤
① 声明对应的头文件:
输出文件流 |
输入文件流 |
输入输出文件流 |
ofstream |
ifstream |
fstream |
② 创建相应的输入输出流对象;
③ 打开相应的文件(其实②,③步可以合并),并判断文件是否可以正常打开;
④ 对文件进行相应的读写操作;
⑤ 关闭文件流,注意:当你不关闭文件时,系统是无法将缓存区内的数据写入到文件当中的。
代码示例
#include <iostream> // 声明相应的头文件
#include <fstream>
using namespace std;
int main()
{
ofstream ofs; // 创建输出流对象
ofs.open("C:\\Users\\hgq15\\Desktop\\test.txt", ios::out | ios::trunc); // 以ios::out + ios::trunc模式打开文件
if (!ofs.is_open()) // 判断文件可以正常打开
{
cout << "文件读写失败" << endl;
return 0;
}
ofs << "文件读写成功" << endl; // 对文件进行写操作
ofs.close(); // 关闭文件流,将缓存区内的数据写入文件当中
}
文本文件的读操作
文件读操作的实质
文本文件的读操作,其实如果我们一个字符一个字符的读入,最终都是读入的ASCII字符,我们如果需要其它类型的数据,我们必须将ASCII强转为其它类型,所用的强转函数如下:
强转函数名称 |
函数调用格式 |
atof |
double atof (const char* str) |
atoi |
int atoi (const char * str) |
atol |
long int atol ( const char * str ) |
atoll |
long long int atoll ( const char * str ) |
代码示例
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
ifstream ifs("C:\\Users\\hgq15\\Desktop\\test.txt",ios::in); // 声明输入文件流对象与相应文件的打开
if (!ifs.is_open()) // 判断文件是否被正常打开
{
cout << "文件打开异常" << endl;
return 0; // 如果文件打开异常,直接停止运行程序
}
第一种读入方式
//char Buffer[1024] = { 0 };
//while (ifs >> Buffer) // 以单个ASCII(字符)为单位进行读操作
//{
// cout << Buffer;
//}
// 第二种读入方式
string Buffer;
while (getline(ifs, Buffer)) // 以整行为单位进行读操作
{
cout << Buffer << endl;
}
ifs.close();
}
一般文件的读方法
方法一:
// 第一种读入方式
char Buffer[1024] = { 0 };
while (ifs >> Buffer) // 以单个ASCII(字符)为单位进行读操作
{
cout << Buffer;
}
方法二:
// 第二种读入方式
string Buffer;
while (getline(ifs, Buffer)) // 以整行为单位进行读操作
{
cout << Buffer << endl;
}
二进制文件的写操作
二进制写操作函数
函数名 |
函数原型 |
解释 |
Wirte |
write(const char* Buffer, size_t Buffer_size) |
从以Buffer为首的字符型数组中一次性读取Buffer_size个字符以二进制的方式写入文件中 |
代码示例
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
ofstream ofs;
ofs.open("C:\\Users\\hgq15\\Desktop\\test.txt", ios::app | ios::out | ios::binary); // 这里我们在文本文件的结尾上追加写操作
if (!ofs.is_open()) // 判断文件是否正常被打开
{
cout << "文件打开失败" << endl;
return 0;
}
ofs.write((const char*)"C++ Cheer!", sizeof(char) * 9); // 以二进制方式将内容写入文件(其实,二进制下英文与文本文件模式下的无区别,但是汉字有区别会在二进制下出现乱码)
ofs.close(); // 关闭文件写通道
}
二进制文件的读操作
二进制读操作函数
函数名称 |
函数原型 |
解析 |
Read |
Read(char* Buffer, size_t Buffer_Size) |
一次性读取Buffer_Size个字符,装入以Buffer为首地址的字符型数组中 |
代码示例
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
ifstream ifs;
ifs.open("C:\\Users\\hgq15\\Desktop\\test.txt", ios::in | ios::binary);
if (!ifs.is_open()) // 判断文件是否被正常打开
{
cout << "文件打开失败" << endl;
return 0;
}
char Buffer[1024] = { 0 };
ifs.read(Buffer, sizeof(Buffer)); // 二进制文件的读操作
cout << Buffer << endl;
ifs.close(); // 关闭文件流
}
以文本格式读写自定义数据类型
以文本格式对自定义数据类型进行写操作
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
class Person
{
private:
int age;
string name;
public:
Person(int age, string name)
{
this->age = age;
this->name = name;
}
friend ofstream& operator << (ofstream& ofs, Person& PersonObject);
};
ofstream& operator << (ofstream& ofs, Person& PersonObject)
{
ofs << PersonObject.name << "的年龄为" << PersonObject.age; // 不要加endl这样会清空缓存区
return ofs;
}
int main()
{
ofstream ofs;
Person PersonObject(18, "张三");
ofs.open("C:\\Users\\hgq15\\Desktop\\test.txt", ios::app | ios::out);
if (!ofs.is_open())
{
cout << "文件打开失败!" << endl;
return 0;
}
ofs << PersonObject << endl; // 用重载运算符将自定义数据类型以自定义输出的方式输出至txt文件中
ofs.close();
}
文件的IO指针
函数名 |
说明 |
函数原型 |
Seekg(用于文件输入流) |
定位输入文件流指针的位置 |
istream& seekg (int off, ios_base::seekdir way) |
Seekp(用于文件输出流) |
定位输出文件流指针的位置 |
ostream& seekp (int off, ios_base::seekdir way) |
Tellp(用于文件输出流) |
获取当前输出文件流指针距离文件头的位置 |
tellp(void) |
Tellg(用于文件输入流) |
获取当前输入文件流指针距离文件头的位置 |
tellg(void) |
函数中的ios_base::seekdir类型的变量可选选项如下:
名称 |
标识 |
以当前位置为起点定义偏移量 |
Ios::cur |
以文件开头位置为起点定义偏移量 |
Ios::beg |
以结尾位置为起点定义偏移量 |
Ios::end |
以文本格式进行自定义数据类型的读操作
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
class Person
{
private:
int age;
string name;
public:
Person(int age, string name)
{
this->age = age;
this->name = name;
}
~Person()
{
cout << "析构Person类的对象" << endl;
}
friend ofstream& operator << (ofstream& ofs, Person& PersonObject);
friend ostream& operator << (ostream& cout, Person& PersonObject);
friend ifstream& operator >> (ifstream& ifs, Person& PersonObject);
};
ofstream& operator << (ofstream& ofs, Person& PersonObject)
{
ofs << PersonObject.name << "的年龄为" << PersonObject.age;
return ofs;
}
ifstream& operator >> (ifstream& ifs, Person& PersonObject)
{
char name[5] = { 0 }; // 记得多出来一个字节的空间存放’\0’结束符
char age[3] = { 0 };
if (ifs.is_open() && !ifs.eof())
{
ifs.seekg(0, ios::beg);
ifs.read(name, 4);
PersonObject.name = name;
ifs.seekg(4 + 8, ios::beg); // 需人为计算出来需要读取的信息前的位置
ifs.read(age, 2);
PersonObject.age = atoi(age); // 将ASCII转化为整型数据
}
return ifs;
}
ostream& operator << (ostream& cout, Person& PersonObject)
{
cout << PersonObject.name << "的年龄为" << PersonObject.age;
return cout;
}
int main()
{
Person PersonObject(18, "张三"), PersonObject1(0, "无");
ofstream ofs("C:\\Users\\hgq15\\Desktop\\test.txt", ios::trunc | ios::out);
if (!ofs.is_open())
{
cout << "文件打开失败!" << endl;
return 0;
}
ofs << PersonObject << endl;
ofs.close();
ifstream ifs("C:\\Users\\hgq15\\Desktop\\test.txt", ios::in);
if (!ifs.is_open())
{
cout << "文件打开失败!" << endl;
return 0;
}
ifs >> PersonObject1;
ifs.close();
cout << PersonObject1 << endl;
}
运行结果