マップファイルを外から読み込みたい欲がある
次は実際にファイルを読み書きする。
ファイルは、何も指定しないとどこに読み書きされるかというと、現在実行した環境のカレントディレクトリである。
(だから、とりあえずカレントディレクトリのややこしさを確認したんだね!)
次に、ファイルには大きな枠で分類して2種類のファイルがありそれぞれ扱いが違ったり違わなかったりします。(どっちやねん)
- ファイル
- テキストファイル
- 中身は数値や文字が文字コードで、数字や文字として書かれている
- 文字コードのバイト数毎にテキスト読み込み関数で呼んでいけばいいから、プログラム作るのは結構らくちん
- 数の場合、数値「3.14」が「33 2e 31 34」のように文字になっているので読み込んでから「文字列」⇒「数値」の変換が必要
- 書き込みも何も考えず文字にして書くから、coutで文字を表示するのとほぼ同様に、書き込みできる
- バイナリファイル
- 中身は文字は文字コード、数値は数値のメモリ表現そのまま、をファイルに書き込んでいくスタイル
- すべて2進数で表されているので、文字のみの場合よりファイルサイズが小さくなる場合が多い(何故かは考えてみてね)
- 数の場合、、数値「3.14」がプログラム内でfloatなら「110011 101110 110001 110100」(浮動小数点形式)で書き込まれる。
- 読み込むときには、元の型が何だったかしらないと読込サイズがわからないので、読込サイズを指定しながら読み込む
これももうどっかで習ったかな?
バイナリファイルは、ちゃんと書けているかどうか確認するときちょっとめんどいので、テキストエディタで開くと中身が文字で見える方(テキストファイル)の読み書きをやってみよう。
テキストファイルの書き込み
まずは、書き込みからやるよ。
手順は前に説明したとおり、ファイルオープン⇒好きに書き込み⇒クローズである。
ファイルの読み書きにはfstreamヘッダをincludeして、読み込みにはifstream、書き込みにはofstreamというストリームを使います。(cinとcoutみたいなもんですね)
- "Main.cpp"
# include <Siv3D.hpp> #include <filesystem> #include <fstream> using std::string; using std::ofstream; using std::cout; using std::endl; void Main() { //カレントディレクトリ取得 std::filesystem::path crrpath = std::filesystem::current_path(); Font font{ 30 }; ofstream out_file;//ファイルストリームのインスタンスを作成 string fname = "output.txt"; //書き込み用ファイル名を指定(好きな名前でいいよ) out_file.open(fname, std::ios::out);//ストリームがオープンする //oFileNameのファイル名のファイルを、上書きモードでオープン if (out_file.fail()) { Console.open(); std::cout << "ファイルオープンに失敗しました!" << std::endl; exit(0); } //書き込み部分 int idata = 10; //書き込み用データ char cdata = 's'; //書き込み用データ float fdata = 3.14; //書き込み用データ string str = "Hi! I'm very very happy today.";//書き込み用データ out_file << str << endl;//ストリームにデータを流す out_file << idata << "," << cdata << "," << fdata << endl; out_file << crrpath.string() << endl; out_file.close();//ストリームを閉じる while (System::Update()) { font(ファイルパスをUTF-32にごにょごにょ).draw(Vec2{ 10,Scene::Center().y }, Palette::White); } }
ソースを見るとわかるが、書き込みはcoutでいろいろ表示するときとほとんど同じ感覚である。
いろいろな、ストリームを使うことで、同じような命令でいろいろなことができるのがC++のいいところでもありわかりづらいところでもあるよね。
coutでこう表示するにはどうしたらいいかな?と考えたものをそのまま、ファイルに書き込むことができる。(ので、是非まずはcoutによる出力をマスターしてほしい)
Missions
- プログラムを実行して、ファイルができていることを確認(中身が指定したとおりになっているかも確認)
- ファイルオープンが成功したら(分岐がひつよう)絶対パスが取得できるので
- std::filesystem::path absPath;を宣言しておいて
- absPath = std::filesystem::absolute(fname);
- で、オープンしたファイルの絶対パスを取得し、書き込みファイルストリームに流してみよう
- カレントディレクトリを移動して、実行ファイルの場所を移動した時にどうなるか確認
- ファイルを上書きモードではなく、追記モードで開く方法を調べ使ってみる
- この辺に答えが書いてあるよ
- 余裕のある人は、マップのデータや、現在のプレイ内容などをデータファイルに保存するにはどうしたらいいかな?って考えてみよう(実装しなくていいよ)