Entry

プログラミングメモ - std::istream のバイナリ読み取り

2010年04月17日

知ってる人には当たり前の話なんだけれども,std::istream 周りのスニペットをメモ。

バイナリファイルを読み書きする場合,手元でバッファを作っておいて,バッファサイズ単位(ブロック単位)で読み書きするのが普通です。一般的なお作法なので,ライブラリの側もそうした制御が呼び元で行われていることを前提にしていることが多い。

で,ブロック単位で読み込む場合,ファイルがブロックサイズの倍数ちょっきりで終わるなんてことはまずないわけで,最後に半端なバイト数が読まれることになります。このバイト数が分からないと,呼び先のライブラリに渡すことができません。

この点,C の fread(3) では,返値が読み込んだバイト数になるので,取得するのは簡単です。一方,C++ の場合はというと,同じようなメソッドである std::istream::read メソッドを使って読むものの,返値が std::istream& なので,読み込んだバイト数を取得する方法が,ぱっと見分からなかったりします。stdio.h から iostream に移行したばかりの向きは,ちと混乱するかも。

多分,一番スマートに読む方法は,こんな感じになるんだと思います。

#include <iostream>
#include <fstream>

int
main(int argc, char* argv[]) {
  std::ifstream ifs;

  if(argc < 2) {
    std::exit(-1);
  }
  // open file
  ifs.open(argv[1], std::ios::binary);
  if (ifs.bad()) {
    std::exit(-2);
  }
  // read file
  const std::size_t blockSize = 256;
  char buf[blockSize];
  int n = 0;
  while ((n = ifs.read(buf, blockSize).gcount()) > 0) {
    std::cout << n << " ";
  }
  std::cout << std::endl;

  return 0;
}

このソースをそのままこのプログラムに食わせた場合,結果はこうなる。

256 219

ま,知ってる人は知ってるわけですけどね。std::istream::gcount メソッドは,割とよく使われるよ,と,ただそんだけ。

Trackback
Trackback URL:
Ads
About
Search This Site
Ads
Categories
Recent Entries
Log Archive
Syndicate This Site
Info.
クリエイティブ・コモンズ・ライセンス
Movable Type 3.36
Valid XHTML 1.1!
Valid CSS!
ブログタイムズ

© 2003-2012 AIAN