序文
ストリームの性質に関する疑問は、私が初めて C++ を学習し始めたときから存在していました。当時、私はたくさんの情報を見つけましたが、いつも知っているようでなぜか分からない状態で、フローの本質が未だに理解できておらず、ずっと無知なままでした。
しかし今日、気まぐれにストリーム関連の情報を調べていたら、ふとわかったようなことがあったので、このブログに記録しておきます。
あらかじめお断りしておきますが、以下の内容は私個人の理解によるものであり、個人的な知識や経験の蓄積により至らない点があるかもしれませんので、間違いがあれば修正してください。
流れの理解
ストリームの本質はオブジェクトです。
ストリームは、データとプログラムの間の中間デバイスです。
ストリームが存在するため、データを直接操作する必要はありませんが、ストリームを操作することで間接的にデータを操作できます。
ストリームの利点
統一された運用基準。
データの種類や種類に関係なく、データがストリームに関連付けられていれば、データの格納方法を考慮する必要はなく、ストリームの運用規格に従って動作するだけで済みます。 . Unityの運用基準です。
前述したように、ストリームの本質はオブジェクトであるため、ストリームには多くのメソッドがあり、これらのメソッドはデータを操作するための統一されたインターフェイスを提供し、コードを変更せずに異なるデータを操作することもできます。
C++ におけるストリームの分類
C++ 中間ストリームは主に 3 つのカテゴリに分類されます。
- IOストリーム: 入力および出力ストリーム、iostream
- ファイルストリーム: ファイル操作の場合は、fstream
- 文字列ストリーム: 主に文字列に対する操作、stringstream を実装します。
私流
これら 3 つは本質的には同じであり、いずれも抽象メソッドですが、操作の対象が異なります。これらのクラス間の関係図を以下に示します。
fstream 自体が iostream から継承されているため、fstream が cin/cout と同じように使用できると言われる理由は、上図からわかります。
文字列ストリーム
基本的な考え方
メモリ内の文字列型変数を入出力オブジェクトとして使用します。
特徴:
- 標準の入出力ストリームと同様に、テキストとバイナリ間の変換が可能です。
- データを文字列に保存 ⇔ \Leftrightarrow ⇔ cout バイナリを ASCII に変換します。
- string ⇔ \Leftrightarrow ⇔ cin ASCII からバイナリにデータを取得します。
- 開閉する必要はありません。
- さまざまな種類のデータを保存できます。
使用
#include <sstream>
ostringstream ostr;//输出流
istringstream istr;//输入流
stringstream str;//输入/输出流
文字列ヘッダー ファイルは、メモリ IO 操作をサポートする 3 つの型を定義しており、文字列が IO ストリームであるのと同様に、これらの型は文字列にデータを書き込み、文字列からデータを読み取ることができます。
isstringstream は string からデータを読み取り、ostringstream は string にデータを書き込み、stringstream は string へのデータの書き込みと string へのデータの読み取りの両方が可能です。
#pragma once
#include<iostream>
#include<sstream>
#include<string>
class Stream {
public:
Stream() {}
Stream(std::string& str)
:str_(str)
{}
~Stream() {};
//输出流
void OsStringStream();
//输入流
void IsStringStream();
//输入输出流
void StringStringStream();
protected:
std::string str_;
};
#include"stream.h"
void Stream::OsStringStream() {
std::ostringstream oss(str_);
std::cout << oss.str() << std::endl;
}
void Stream::IsStringStream() {
std::string line;
std::istringstream iss(str_);
std::getline(iss, line);
std::cout << line << std::endl;
//创建输入流
std::istringstream str;
//拷贝字符串到输入流中
str.str("bye bye");
//用str_str返回str.str()的拷贝
std::string str_str = str.str();
std::cout << str_str << std::endl;
}
void Stream::StringStringStream() {
std::stringstream ss1(str_);
std::cout << ss1.str() << std::endl;
}
#include"stream.h"
int main() {
std::string str("ni hao");
Stream stream(str);
stream.IsStringStream();
stream.OsStringStream();
stream.StringStringStream();
return 0;
}
ファイルストリーム fstream
プログラムの実行中、生成されたデータは一時データであり、プログラムの実行が終了すると解放され、データはファイルを通じて永続化できます。C++ では、ファイル操作のためにヘッダー ファイル < fstream > をインクルードする必要があります。テキストには次の 2 種類があります。
(1) テキストファイル:ASCIIコードのテキスト形式でコンピュータに保存されるファイルです。
(2) バイナリ ファイル: ファイルはバイナリ形式のテキストでコンピュータに保存され、通常はユーザーが直接読み取ることはできません。
オペレーティング ファイルの 3 つのカテゴリ:
-
ストリーム: 書き込み
-
ifstream: 読み取り
-
fstream: 読み取りと書き込み
テキストファイル
ファイルを書き込む
次のように進めます。
- インクルードヘッダーファイル: #include<fstream>
- ストリーム オブジェクトを作成します。 ofstream ofs;
- ファイルを開きます: ofs.open("ファイル パス", open メソッド);
- 書き込みデータ: ofs<<"書き込みデータ";
- ファイルを閉じます: ofs.close();
オープンメソッド:
注: ファイルを開くメソッドは | 演算子と組み合わせて使用できます。
void Csv::WriteCsvFile() {
//std::ofstream out_file("data.csv", std::ios::out); //std::ios::out 文件不存在则创建文件,有文件则清空文件
std::ofstream out_file;
out_file.open("data.csv", std::ios::out);
if (!out_file) {
std::cout << "open file failed" << std::endl;
return;
}
for(int i = 0; i < 5; ++i) {
out_file << 12 << ",";
out_file << 13 << ",";
out_file << 14 << std::endl;
}
out_file.close();
std::cout << "write file successed" << std::endl;
}
ファイルを読み取る
次のように進めます。
- インクルードヘッダーファイル: #include<fstream>
- ストリーム オブジェクトを作成します: ifstream ifs;
- ファイルを開いて、ファイルが正常に開かれたかどうかを判断します。 ifs.open("ファイル パス", open メソッド);
- データの読み取り:4つの読み取り方法
- ファイルを閉じます: ifs.close();
#pragma once
#include<iostream>
#include<fstream>
#include<string>
#include<sstream>
class Csv {
public:
Csv() {}
~Csv() {}
void ReadCsvFile();
void WriteCsvFile();
};
#include"csv.h"
void Csv::ReadCsvFile() {
//std::ifstream in_file("data.csv", std::ios::in);
std::ifstream in_file;
in_file.open("data.csv", std::ios::in);
if (!in_file) {
std::cout << "open fill failed" << std::endl;
}
int num = 0;
std::string line;
std::string file;
while (std::getline(in_file, line)) {
std::string file;
// 将整行字符串line读入到字符串流iss中
std::istringstream iss(line);
std::getline(iss, file, ',');
//将刚刚读取的字符串转换成int
std::cout << std::atoi(file.c_str()) << " ";
std::getline(iss, file, ',');
std::cout << std::atoi(file.c_str()) << " ";
std::getline(iss, file, ',');
std::cout << std::atoi(file.c_str()) << std::endl;
num++;
}
std::cout << "读取了" << num << "行" << std::endl;
if (5 == num) {
std::cout << "read file success" << std::endl;
}
in_file.close();
}
void Csv::WriteCsvFile() {
//std::ofstream out_file("data.csv", std::ios::out);
std::ofstream out_file;
out_file.open("data.csv", std::ios::out);
if (!out_file) {
std::cout << "open file failed" << std::endl;
return;
}
for(int i = 0; i < 5; ++i) {
out_file << 12 << ",";
out_file << 13 << ",";
out_file << 14 << std::endl;
}
out_file.close();
std::cout << "write file successed" << std::endl;
}
#include"csv.h"
int main() {
Csv csv;
csv.WriteCsvFile();
csv.ReadCsvFile();
return 0;
}
各ファイル ストリームにはデフォルトのファイル モードがあり、ifstream に関連付けられたファイルはデフォルトで in モードで開かれ、ofstream に関連付けられたファイルはデフォルトで out モードで開かれ、fstream に関連付けられたファイルはデフォルトで in and out モードで開かれます。
ofstream out; // 未指定文件打开模式
out.open("test.txt"); // 模式隐含设置为输出和截断
out.close(); // 关闭out
out.open("test2.txt",ofstream::app); //模式为输出和追加
out.close(); //关闭out