1. 数据流的概念
数据流是一组有序的,有头和尾的字节的数据序列。分为输入流和输出流。
流是一种灵活且面向对象的I/O方法。
根据操作对象不同分为文件流、字符串流、控制台流。
控制台流
C++输入输出操作分别是由istream(输入流)和ostream(输出流)这两个类提供的,
为了允许双向的输入/输出, 由istream和ostream派生出了iostream类。
函数 | 功能 | 应用 |
cin | 输入的istream类对象 | 从设备读入数据 |
cout | 输出的ostream类对象 | 向设备输出或者写数据 |
cerr | 标准错误的ostream类对象 | 屏幕设备写数据 |
文件流
文件流的输入输出类在fstream头文件被定义,和控制台流继承关系为:
ofstream类的默认构造函数原形为:
ofstream::ofstream(constchar *filename,int mode = ios::out, int penprot = filebuf::openprot);
参数 | 值来源 |
filename | 打开的文件名 |
mode | 打开文件的模式(ios::out) |
prot | 打来文件属性(filebuf::openprot) |
mode属性表
类型 | 解释 |
ios::app | 追加方式打开文件 |
ios::ate | 文件打开后定位到文件尾,app就包含此属性 |
ios::binary | 以二进制方式打开文件,缺省的方式是文本方式 |
ios::in | 文件以输入方式打开 |
ios::out | 文件以输出方式打开 |
ios::nocreate | 不建立文件,所以文件不存在时打开失败 |
ios::noreplace | 不覆盖文件,打开文件时如果文件存在就失败 |
打开文件属性值
类型 | 解释 |
0 | 普通文件,打开访问 |
1 | 只读文件 |
2 | 隐含文件 |
4 | 系统文件 |
“或”或者“ + ”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。
文件使用完后要使用close成员函数关闭文件。
字符串流
字符串流就是能够控制字符串类型对象进行输入输出的类。
istrstream C风格的串流的输入操作,字符串数组作为输入。
ostrstream C风格的串流的输出操作,字符串数组作为输出。
strstream 支持C风格的串流的输入输出操作。
2. 文件处理简介
C++ 通过以下几个类支持文件的输入输出:
- ofstream: 写操作(输出)的文件类 (由ostream引申而来)
- ifstream: 读操作(输入)的文件类(由istream引申而来)
- fstream: 可同时读写操作的文件类 (由iostream引申)
文件处理基本流程
3. 文件的输入与输出
打开文件
在从文件读取信息或者向文件写入信息之前,必须先打开文件。
ofstream对象打开文件进行写操作。
ifstream 对象打开文件进行读操作。
fstream对象可打开文件进行读写操作。
open()语法:
void open(const char *filename, ios::openmode mode)
filename指定要打开的文件名称和路径
mode定义文件打开模式
模式标志 | 描述 |
ios::app | 追加模式,所有写入都追加到文件末尾 |
ios::ate | 文件打开后定位到文件末尾 |
ios::in | 打开文件用于读取 |
ios::out | 打开文件用于写入 |
ios::trunc | 截断写入 |
默认打开方式
类 | 参数得我默认方式 |
ofstream | ios::out |ios::trunc |
ifstream | ios::in |
fstream | :ios::in |ios::out |
写入与读取
写入:使用流运算符(<<)
读取:使用流运算符(>>)
关闭文件
当 C++ 程序终止时,它会自动关闭刷新所有流,释放所有分配的内存,并关闭所有打开的文件。
但写程序时应该养成一个好习惯,在 程序终止前关闭所有打开的文件。
语法:
void close();
4. 文件写入案例
#include<iostream>
#include<fstream>
using namespace std;
int main()
{
//创建流对象
ofstream outf;
//打开文件
outf.open("file.txt");//outf.open("file.txt",ios::out|ios::trunc)
//写入内容
outf << " 恋恋 " << endl;
outf << " 恋恋天下第一可爱" << endl;
outf << " 514是恋恋的生日(迫真) " << endl;
//关闭文件
outf.close();
}
5. 文件读取案例
在c++中使用ifstream读文件的时候会以空格为分隔符,遇到空格就不读取了。这时候可以调用get函数来读取内容。
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main()
{
string s1;
ifstream inf;
inf.open("file.txt");
while (getline(inf, s1))
{
cout << s1 << endl;
}
inf.close();
}
6. 二进制文件读写
写文件
二进制写文件主要利用流对象调用成员函数write()
函数原型:
ostream& write(const char*buffer,int len);
buffer指向内存中一段空间
len是写字节数
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
class Student{
public:
Student(){}
Student(string name,int age):name(name),age(age){}
protected:
string name;
int age;
};
void test()
{
ofstream of;
Student s1("恋恋", 18);
of.open("student.txt", ios::binary|ios::out);
of.write((const char *)&s1, sizeof(Student));
of.close();
}
int main()
{
test();
return 0;
}
读文件
二进制读文件主要利用流对象调用成员函数read。
函数原型:
istream& read( char*buffer,int len);
buffer指向内存中一段空间
len是读字节数
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
class Student{
public:
Student(){}
Student(string name,int age):name(name),age(age){}
void show() { cout << "名字是" << this->name << " 年龄是" << this->age << endl; }
protected:
string name;
int age;
};
void test()
{
ifstream of;
Student s1;
of.open("student.txt", ios::binary|ios::in);
of.read((char *)&s1, sizeof(Student));
of.close();
s1.show();
}
int main()
{
test();
return 0;
}
7. fstream文件操作
fstream支持ifstream和ofstream的所有操作。
打开文件:
使用构造函数声明对象时打开文件,示例:
fstream file(filename, ios::in | ios::out)
使用open()函数打开文件,函数原型:
void open(const char* filename,int mode,int access)
模式和属性可以单独使用给,也可以混合使用。混合使用时,用逻辑连接符或 |连接
fstream提供的读写操作有:>、read()、write()、put()、get()、getline()。根据文件类型可分为文本文件和二进制文件,根据读写方式可分为逐行读写和整块读写。通常,文本文件使用逐行读写的方式,二进制文件使用整块读写的方式。
文本文件读写:
逐行写入文本文件可以使用操作符<<。
逐行读取文本文件时可以使用getline()函数。
二进制文件的读写
使用write()、put()函数写入二进制文件。
使用read()、get()读 取二进制文件。
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
class Student{
public:
Student(){}
Student(string name,int age):name(name),age(age){}
void show() { cout << "名字是" << this->name << " 年龄是" << this->age << endl; }
protected:
string name;
int age;
};
void test()
{
ifstream of;
Student s1;
of.open("student.txt", ios::binary|ios::in);
of.read((char *)&s1, sizeof(Student));
of.close();
s1.show();
}
int main()
{
string str;
fstream fstr("file.txt", ios::in | ios::out | ios::trunc);
fstr << "测试恋恋能不能写入" << endl;
fstr<<"第一次写入"<<endl;
fstr << "写入完毕" << endl;
fstr.close();
fstr.open("file.txt", ios::in );
while (getline(fstr, str))
{
cout << str << endl;
}
cout << "恋恋读取完毕" << endl;
fstr.close();
return 0;
}
8. 文件定位和大小
C++的文件定位分为读位置和写位置的定位,对应的成员函数分别为seekg()和seekp()。 seekg()函数设置读位置,seekp()设置写位置。函数原型如下:
istream& seekg(streamoff offset,seek_dir origin);
ofstream& seekp(streamoff offset,seek_dir origin)
offset表示偏移量
origin表示移动的基准
ios::beg 文件开头
ios::cur 文件当前位置
ios::end 文件结尾
示例
inFile.seekg(2,ios::beg); // 把文件读指针从开始位置向后移动2个字节 outFile.seekp(2,ios::cur); // 把文件写指针从当前位置向后移动2个字节
获取文件大小可以使用seekg()和tellg()或者seekp()和tellp()函数结合使用的方式。
示例:
inFile.seekg(0,ios::end); // 读文件指针移动到文件末尾
streampos ipos = inFile.tellg(); //返回当前指针的位置,也就是文件的大小,单位是字节