CPPIO流
IO流
一、C++流介绍
流
定义:一段有序的字节序列
作用:主要用程序读取和写入数据
1、基本概念
流(Stream):在C++中,IO操作是通过流来完成的。流被看作是从源(如文件、键盘、网络连接等)到目标(如内存、磁盘等)的数据传输通道。
这种通道可以是单向的(如输入流或输出流)或双向的(如支持读写的文件流)。通过流可以实现程序与文件、网络套接字等进行数据交互。
2、C++中的流类库
C++中I/O(输入/输出)标准类定义在iostream
,fstream
,strstream
3个头文件中,对应的是标准I/O流、文件I/O流、字符串I/O流。
- 标准I/O流:涉及到与程序的标准输入(
cin
,通常关联着键盘)和标准输出(cout
,通常关联着屏幕)设备的交互。此外,还包括错误输出流(cerr
)和日志输出流(clog
)等。 - 文件I/O流:用于读写外部文件。C++提供了如
ifstream
(用于读取文件)、ofstream
(用于写入文件)和fstream
(既能读也能写)等类来处理文件操作。 - 字符串I/O流:允许程序将数据读取到或写入到字符串中,主要通过
istringstream
(读取字符串)、ostringstream
(写入字符串)和stringstream
(可读写字符串)类实现。
各头文件包含的常用类如下:
- 进行标准I/O操作时使用
iostream
头文件,它包含ios、iostream、istream、ostream等类 - 进行文件I/O操作时使用
fstream
头文件,它包含fstream、ifstream、ofstream和fstreambase等类 - 进行串I/O操作时使用
sstream
头文件,它包含istringstream、ostringstream、stringstream等类
二、ifstream流
ifstream
是 C++ 标准库中的一个类,用于从文件中读取数据。它是istream
类的派生类,因此继承了所有用于输入操作的功能。使用ifstream
可以打开文件、读取数据,并在完成操作后关闭文件。
1、打开文件
首先包含头文件:
#include <fstream>
using namespace std;
(1)构造函数
方式一,可以直接在创建 ifstream
对象时指定文件路径。
ifstream inputFile("example.txt");
(2)open()函数
方式二,先创建对象,然后使用 open
函数指定文件路径。
ifstream inputFile;
inputFile.open("example.txt");
(3)状态检查
fail()
成员函数用来检查流是否处于失败状态,这包括读取或写入错误、格式匹配错误等情况。如果之前的操作导致流进入失败状态(比如文件打开失败,或者读写操作遇到不可恢复的错误),则fail()
将返回true
。此检查广泛用于确定是否出现了任何类型的错误。
int main()
{ifstream inputFile("data.txt");if (inputFile.fail()){cerr << "无法打开文件!" << endl;return 0;}
}
或则:
if (!inputFile)
{cerr << "无法打开文件!" << endl;return 0;
}if(!inputFile.is_open())
{std::cout << "文件打开失败" << std::endl;return -1;
}
这种用法利用了流对象可以直接作为布尔条件表达式的特性。当流对象用作条件时,它会隐式转换为其内部的bool
值,这个值由!stream.fail()
决定。如果流是好的(没有失败),表达式值为true
;如果流失败了,则为false
。所以这条语句也是检查流是否失败,与直接调用fail()
效果相同,但在语法上更加简洁。
2、读取数据
(1)字符读取
get(ch)
函数用于读取一个字符。其中,ch
是一个字符变量,用来接收从文件中读取的字符。
char ch;
inputFile.get(ch);
cout << ch << endl;
如果成功读取到字符,该字符会被存储到 ch
中。
循环读取文件中的字符:
char ch;
while (inputFile.get(ch))
{cout << ch;
}
(2)读取一行
getline
函数来自 <string>
头文件,专门用于处理 std::string
类型。其原型为:
std::istream& getline(std::istream& is, std::string& str, char delim = '\n');
读取的文本将存储到字符串中,delim
:默认分隔符是换行符(\n
)。
int main()
{//==========读取一行===============ifstream stream("example.txt");std::string line;std::getline(stream, line);cout << "读取一行数据:" << line << endl;//=====读取全部=====//循环继续调用getline读取剩余的每一行,直到文件结束。while (std::getline(stream, line)){cout << "读取一行数据:" << line << endl;}
}
3、提取运算符 (>>
)
用于输入操作,从流中提取数据。例如,cin >> variable
会从标准输入设备读取数据并存储到变量中。
另外,提取运算符可以连续使用,用于从流中顺序读取多个数据项。例如,从标准输入读取两个数字:
ifstream inputFile("example.txt");
int number;
double decimal;
inputFile >> number >> decimal;
空白跳过:默认情况下,>>
会自动跳过前导空白字符(如空格、制表符、换行符)。
ifstream
使用提取运算符,循环从流中读取数据:
ifstream inputFile("example.txt");
string s;
while (inputFile >> s) { cout << "s: " << s << endl;
}
4、关闭流
- 显式关闭:
inputFile.close();
- 自动关闭:当
ifstream
对象离开作用域时,流会自动关闭。
三、ofstream流
ofstream
类,是std::ostream
的派生类,用于处理文件的输出操作,即写入数据到文件中。
ofstream
可以创建新文件或覆盖现有文件并向其写入数据。ofstream
在 <fstream>
头文件中。
1、创建流对象
创建一个 ofstream
类型的对象,可以在构造函数中指定文件名,或者先声明后使用 open()
函数指定文件。
std::ofstream outputFile("output.txt");
2、检查状态
使用 is_open()
成员函数检查文件是否成功打开。
if (!outputFile.is_open()) {std::cerr << "无法打开文件!" << std::endl;return 0;
}
3、写入数据
使用插入运算符 <<
向文件写入各种类型的数据,如字符串、数字等。
int main()
{ofstream outputFile;outputFile.open("data.txt");if(outputFile.is_open()){ outputFile << "hello world!\n";outputFile << 100 << std::endl;}else{cout << "文件打开失败" << endl;}outputFile.close();return 0;
}
4、关闭流
操作完成后,可以通过调用 close()
方法手动关闭,也可以在对象生命周期结束时也会自动关闭。
outputFile.close();
5、文件流模式
默认以覆盖模式打开文件,如果需要追加内容而不是覆盖,可以在打开文件时设置相应的模式。
打开方式在ios类中定义,有输入方式、输出方式和追加方式等。
方式 | 作用 | ifstream | ofstream | fstream |
---|---|---|---|---|
ios::in | 用输入方式打开,只能读不能写 | √ | × | √ |
ios::out | 用输出方式打开,只能写不能读 | × | √ | √ |
ios::app | 以追加的方式打开文件,打开后文件指针在文件尾部,可以改写 | × | √ | √ |
ios::binary | 以二进制方式打开文件 | √ | √ | √ |
上述参数可以结合运算符|
一起使用,例如:
ios::in | ios::out 以读写方式打开文件,对文件可读可写
ios::in | ios::binary 以二进制方式打开文件,可以进行读操作
int main()
{//使用追加模式打开文件ofstream outputFile("data.txt", ios::app);if(outputFile.is_open()){ outputFile << "hello world!\n";outputFile << 100 << std::endl;}else{cout << "文件打开失败" << endl;}outputFile.close();
}
6、图片复制案例
#include <fstream>
#include <iostream>int main () {std::ifstream input("123.png",std::ios::binary);std::ofstream output("456.png", std::ios::binary);char buffer[1024];while (input.read(buffer,1024)) {output.write(buffer, input.gcount()); //input.gcount():输出流每次读取真实大小}if (input.gcount() > 0) {output.write(buffer, input.gcount());}//图片较小可以直接用下面代码//output << input.rdbuf();return 0;
}
或者
#include <iostream>
#include <fstream>//包含输入输出流头文件
using namespace std;
int main03()
{//复制照片ifstream input("OIP-C.webp", ios::binary);//二进制方式打开if(!input.is_open()){cout << "文件打开失败" << endl;return -1;}else{cout << "文件打开成功" << endl;}//输出文件流ofstream output("copy.webp", ios::binary);//二进制方式打开if(!output.is_open()){cout << "文件打开失败" << endl;return -1;}else{cout << "文件打开成功" << endl;}//读取数据char ch;while(input.get(ch)) //读取一个字符{output.put(ch); //写一个字符}//关闭流input.close();return 0;
}