■ C++のバイナリファイル入出力 ■ ■ 初めに
此処では、Visual Studio 2017 を起動し、新しいプロジェクトで、Visual C++の Windows デスクトッ プを選択し、Windows コンソールアプリケーションを作成する。
■ 使用クラス
C++の場合、ファイルの入出力に使用するクラスは、ifstream、ofstream、fstream の 3 種類が有り、 頭に i(input)が付いた ifstream が入力、o(output)が付いた ofstream が出力、何も付かない fstream が両用を表す。 クラス名 入出力別 派生元クラス ifstream 入力 istream ofstream 出力 ostream fstream 両用 iostream 孰れも fstream をインクルードする事で使える様に成る。 #include <fstream>
フ
ファ
ァイ
イル
ルの
の入
入出
出力
力
■ オープンモード オープンモードは、列挙型 open_mode の各ビットの論理和(OR)を取って設定する。open_mode は、 ios クラスの公開部で下記の様に定義されて居る。 入出力別 モード 値 解説 両用 ios::binary 0 ファイルをバイナリモードで開く ios::in 1 読み込み専用で開く 入力 ios::ate 4 開く時に EOF 迄移動する ios::out 2 出力用にファイルを開く ios::app 8 追加(アペンド)出力 出力 ios::trunc 16 既存のファイルを上書きする 出力モードでバイナリファイルをオープンする時は、下記の孰れかを記述する。 std::ofstream toFile ("sample.bin", std::ios::binary);
std::fstream inoutFile ("sample.bin", std::ios::binary|std::ios::out);
入力モードでバイナリファイルをオープンする時は、下記の孰れかを記述する。 std::ifstream fromFile ("sample.bin", std::ios::binary);
std::fstream inoutFile ("sample.bin", std::ios::binary|std::ios::in);
入出力両用でファイルをオープンする時は、ios::in と ios::out の和をモードに指定する。 std::fstream inoutFile ("sample.bin", std::ios::binary|std::ios::in|ios::out);
■ ファイルのオープンとクローズ
下記の様に、コンストラクタにファイル名を指定した場合、ファイルストリームのインスタンスが生成 されると同時に、ファイルがオープンされる。
std::ifstream fromFile("sample.bin", std::ios::binary);
if (!fromFile) std::cout << "Unable to open for input mode !¥n"; else std::cout << "Successfully open for input mode !¥n"; fromFile.close();
std::ofstream toFile("sample.bin", std::ios::binary);
if (!toFile) std::cout << "Unable to open for output mode !¥n"; else std::cout << "Successfully open for output mode !¥n"; toFile.close();
std::fstream inoutFile("sample.bin", std::ios::binary | std::ios::in | std::ios::out); if (!inoutFile) std::cout << "Unable to open for in/out mode !¥n";
else std::cout << "Successfully open in/out mode !¥n"; inoutFile.close(); 亦、下記の様に、ファイルを指定せずにファイルストリームの宣言丈を行い、後にファイルを明示的に オープンする事も出来る。 std::ifstream fromFile; fromFile.open("sample.bin", std::ios::binary); fromFile.close();
std::ofstream toFile;
toFile.open("sample.bin", std::ios::binary); toFile.close();
std::ofstream inoutFile;
inoutFile.open("sample.txt", std::ios::binary | std::ios::out|std::ios::out); inoutFile.close(); コンストラクタにファイル名を指定してオープンしたり、open 関数を使用してオープンしたファイル は、ファイルストリームが破棄された時点(delete するか、スコープ外に出る時点)で自動的にクロー ズされるが、オープンしたファイルは、必ず close でクローズする物だと憶えて欲しい。 ■ 入力 バイナリファイルからデータを読み込む時、下記のモードでファイルをオープンする(ios::in は ifstream では不要)。 モード 解説 ios::in 読み込み専用で開く ios::binary ファイルをバイナリモードで開く 読み取り専用モードで開くには、下記の様に記述する。 std::ifstream fromFile("sample.bin", std::ios::binary); std::ifstream fromFile;
fromFile.open("sample.bin", std::ios::binary);
std::fstream inoutFile ("sample.bin", std::ios::binary|std::ios::in); std::fstream inoutFile; inoutFile.open("sample.bin", std::ios::binary|std::ios::in); 下記に、バイナリファイル sample1.bin より、int 型のデータを 2 個連続で読み込むコードを示す。 #include "stdafx.h" #include <iostream> #include <fstream> int main() { int dat; std::ifstream fromFile; fromFile.open("sample1.bin", std::ios::binary);
if (!fromFile) std::cout << "Unable to open for input mode !¥n"; else std::cout << "Successfully open for input mode !¥n"; fromFile.read((char*)&dat, sizeof(int));
std::cout << dat << std::endl;
fromFile.read((char*)&dat, sizeof(int)); std::cout << dat << std::endl;
fromFile.close(); return 0; } バイナリファイル sample1.bin はデバッ グ時には、ソースファイル(.cpp)と同 じディレクトリに格納されて居る物と する。
猶、総てのデータを読み込むには、ファイルの終端に達すると true に成る eof 関数(End of file)を利 用する。 std::ifstream fromFile; fromFile.open("sample.bin", std::ios::binary); while (!fromFile.eof( )) { fromFile.read((char*)&dat, sizeof(int)); std::cout << dat << std::endl;
} fromFile.close( ); 下記に、バイナリファイル sample2.bin より、構造体 Person 型のデータを読み込むコードを示す(先 に出力のサンプルコードで sample2.bin を作成して置くと結果が確認出来る)。 #include "stdafx.h" #include <iostream> #include <fstream> struct Person { char name[20]; char sex; int age; double height; double weight; }; int main() { Person p; std::ifstream fromFile; fromFile.open("sample2.bin", std::ios::binary); fromFile.read((char*)&p, sizeof(p));
printf("%s %c %d %f %f¥n¥n", p.name, p.sex, p.age, p.height, p.weight); fromFile.close(); return 0; } ■ 出力 バイナリファイルにデータを書き込む時、下記のモードでファイルをオープンする(ios::out は ofstream では不要)。 モード 意味 ios::out 出力用にファイルを開く ios::binary ファイルをバイナリモードで開く 下記に、バイナリファイル sample1.bin に、int 型のデータを 2 個連続で書き込むコードを示す(上書 きモードなので元のデータは消去される)。 バイナリファイル sample2.bin はデバッ グ時には、ソースファイル(.cpp)と同 じディレクトリに格納されて居る物と する。
#include "stdafx.h" #include <iostream> #include <fstream> int main() { int dat; std::ofstream toFile; toFile.open("sample1.bin", std::ios::binary);
if (!toFile) std::cout << "Unable to open for output mode !¥n"; else std::cout << "Successfully open for output mode !¥n"; toFile.write((char*)&dat, sizeof(int));
dat -= 1;
toFile.write((char*)&dat, sizeof(int)); std::cout << "Saved !" << std::endl; toFile.close(); return 0; } 下記に、バイナリファイル sample2.bin に、構造体 Person 型のデータを書き込むコードを示す(上書 きモードなので元のデータは消去される)。 #include "stdafx.h" #include <iostream> #include <fstream> struct Person { char name[20]; char sex; int age; double height; double weight; }; int main() { char w[20] = "烏賊 太郎"; Person p; strcpy_s(p.name, w); p.sex = 'M'; p.age = 68; p.height = 169.8; p.weight = 64.7;
printf("%s %c %d %f %f¥n¥n", p.name, p.sex, p.age, p.height, p.weight);
std::ofstream toFile;
toFile.open("sample2.bin", std::ios::binary); toFile.write((char*)&p, sizeof(p));
std::cout << "Saved !" << std::endl; toFile.close();
return 0; }
上記の結果、下図の様なバイナリファイルが生成される。構造体のパディング(アライメント)や各デ ータ型の格納法が良く解る。