🐈

[C++] ファイル入出力の覚書

2023/04/22に公開

何回やっても覚えられないし、
いちいちネットであちこち調べるのが面倒なので
自分がよく使う入出力をまとめておく。

C++の場合、使うクラスは
ifstream, ofstreamの2つの種類があり、
ifstream, ofstreamのiが入力、oが出力を表す。

fstreamをインクルードすることで両方使える。

読み込み、書き込みの際、
モードについても抑える必要がある。たとえば
読むときは以下のようにモードを指定する。
(ここでは、「読み取り専用モード」で開いている)

reading_file.open(filename, std::ios::in);

#入力

ファイルを読み込んで、ある区切り文字(デリミタ)で
一行ずつ読む場合は以下のようにする。

モード 意味
ios::ate 開く時にEOFまで移動する
ios::binary ファイルをバイナリモードで開く
ios::in 読み込み専用で開く

よく使うのは、eof()メソッドで、
読み込んでいるファイルが終端まで来たときに、制御を変えることができる。

#include <iostream>  // for debug writing
#include <string>    // useful for reading and writing

#include <fstream>   // ifstream, ofstream
#include <sstream>   // istringstream

int main(int argc, char** argv)
{
  std::string filename = argv[1];

  std::ifstream reading_file;
  reading_file.open(filename, std::ios::in);

  std::string reading_line_buffer;

  std::cout << "reading " << filename << "..." << std::endl;

  while (!reading_file.eof())
  {
    // read by line
    std::getline(reading_file, reading_line_buffer);

    std::cout << reading_line_buffer << std::endl;

    // read by delimiter on reading "one" line
    const char delimiter = ' ';
    std::string separated_string_buffer;
    std::istringstream line_separater(reading_line_buffer);
    std::getline(line_separater, separated_string_buffer, delimiter);

    std::cout << separated_string_buffer << std::endl;

  }

}

ファイルを読むときは、上述のように
クラスを宣言してからopenメソッドで読んでもよいが、
以下のように、コンストラクタを使って一気に読み込んでもよい。

  std::ifstream reading_file(filename, std::ios::in);

#出力

モード 意味
ios::out 出力用にファイルを開く
ios::app 追加出力
ios::trunc 既存のファイルを上書きする
#include <iostream>
#include <string>    // useful for reading and writing

#include <fstream>   // ifstream, ofstream

int main()
{
  std::string filename = "test.txt";

  std::ofstream writing_file;
  writing_file.open(filename, std::ios::out);

  std::cout << "writing " << filename << "..." << std::endl;

  for (int i = 0; i<10; i++)
  {
    writing_file << i << std::endl;
  }

}

#補足
読みこみ・書き込み失敗が
メンバ関数fail()で確認できるので、その
エラー処理を適宜入れるのがよい。

#ややこしい話
fstreamにはメンバ関数getline()があるが、
使えないので基本的に使わない。
代わりに、上で示したように、
STLのstringにあるgetline()を使う。

#TIP
空白が連続していて、読みづらいファイルの場合、
演算子>>を使う。
たとえば、

std::string separated_string_buffer = "";

std::istringstream line_separater(reading_line_buffer);
line_separater >> separated_string_buffer;
line_separater >> separated_string_buffer;
line_separater >> separated_string_buffer;

とすると、空白を飛ばして読める。

Discussion