【C++】ファイルの出力について覚えておくべきこと【忘備録】

スポンサーリンク
homeimageC++
スポンサーリンク

はじめに

前回の記事の続き。

出力ファイルについて覚えておくと便利なオープンモードとファイル位置の設定についての忘備録。

オープンモードについて

前回は次のようにしてファイルを開いた。

std::ofstream オブジェクト名(ファイル);

この場合ファイルは自動的に後で記述する「std::ios::out」というモードで開かれる。

ファイルを開く際のモードは次にようにすることで指定ができる。

std::ofstream オブジェクト名(ファイル,オープンモード);

各オープンモードについて説明する。

std::ios::out

デフォルトで指定されるモード。

書き込みを始めた時点で出力ファイルの内容を全て破棄する。

#include <iostream>
#include <fstream>

int main(){

	std::ofstream ofs("output.txt", std::ios::out); //出力ファイルストリーム
	
	ofs << "Hello World!";
	
 	return 0;
}

このようなプログラムであれば、出力ファイルとして指定されたファイルの内容は、元の内容に関わらず次のようになる。

Hello World!

std::ios::trunc

このモードはファイルを開いた時点で出力ファイルの内容を全て破棄する。

「std::ios::out」との違いは内容を破棄するタイミングのみであり、今回触れる内容では特に差はない。

#include <iostream>
#include <fstream>

int main(){

	std::ofstream ofs("output.txt", std::ios::trunc); //出力ファイルストリーム
	
	ofs << "Hello World!";
	
 	return 0;
}

このようなプログラムであれば、出力ファイルとして指定されたファイルの内容は、元の内容に関わらず次のようになる。

Hello World!

std::ios::app

このモードでは出力ファイルの内容が残り、必ず出力ファイルの末尾に記入する。

ここで必ず出力ファイルの末尾に記入するというのは、書き込みの前に必ず末尾に移動してから書き込むということである。

#include <iostream>
#include <fstream>

int main(){

	std::ofstream ofs("output.txt", std::ios::app); //出力ファイルストリーム
	
	ofs << "Hello World!";
	
 	return 0;
}
A
B
C
D
E

これが出力ファイルの元の内容だとすると、プログラムを実行すると出力ファイルは次のようになる。

A
B
C
D
EHello World!

std::ios::ate

このモードでは出力ファイルの内容が残り、ファイルの好きな位置に記入することができる。

ただし、記入する位置にデータが残っている場合には置き換えられる。

また、リファレンスには「std::ios::ate」モードでは開くと同時にファイルの終端へとシークする(要するに、このモードで開いて何もしなければ「std::ios::app」と同じ状態になる)と書いてあるが、「ofstream」では上手くいかないので次のようにして開くと良い。

std::ofstream ofs(ファイル, std::ios::ate | std::ios::in);

ここで「std::ios::in」はファイルを読み取り状態で開くという意味を持つが、あまり深く考えずに使うこと。

記入する位置の移動、およびこのモードでの実行例については次で説明する。

ファイル位置の変更

主に入力モードを「std::ios::ate」とした場合に、ファイル位置を変更する必要がある場合には次のようにして「seekp」メンバ関数を用いて位置の指定を行う。

ファイルストリームオブジェクト.seekp(基準からの位置,基準);

基準からの位置が0の場合には基準からの位置は書かなくても良い。

基準からの位置はカーソルをキーボードの矢印で動かす回数だと考えれば良い。

使うことのできる位置の基準は次の通り。

std::ios::beg

ファイルの先頭。

std::ios::end

ファイルの末尾。

std::ios::cur

ファイルの中の現在地。

プログラム例

出力ファイルの元の内容が次のようなものだったとする。

A
B
C
D
E
F
G
H
I
J

これに対して次のようなプログラムを用意した。

#include <iostream>
#include <fstream>

int main(){

	std::ofstream ofs("output.txt", std::ios::ate | std::ios::in); //出力ファイルストリーム
	
	ofs.seekp(std::ios::beg); //先頭へ移動
	
	ofs << "a";
	
	ofs.seekp(-2,std::ios::end); //最後から2つ前に移動
	
	ofs << "h" << "i" << std::endl;
	
	ofs << "j";
	
 	return 0;
}

実行した結果出力ファイルの内容は次のようになる。

a
B
C
D
E
F
G
H
Ihi
j

プログラムについて簡単に説明する。

最初にファイルの先頭に移動した。ここで「A」があるが先ほど説明したが、禁輸する場所に元のデータがある場合には書き換えられるため、「a」に書き換えられた。

「I」が消えなかったのは、このプログラムでは最終点からカーソルを左矢印で2回移動させているのだが2回の移動では「I」の後ろまでしか移動しない。勝手な改行をすることはないため「I」の後ろに「h」「i」が書き出され、改行した。

ここで「J」があったが「j」を書き出す際に書き換えられた。

最後に

ファイル関連については、まだまだ覚えておくべきことがたくさんあるのでそのうちに。

コメント

タイトルとURLをコピーしました