2011-01-13 8 views
3

グイド・ヴァンロッサムはこのarticleでのPythonのシンプルさを実証し、バッファリングのために、この機能を使用する読み込み、未知の長さのファイルの読み込み:私はする必要があり等価は

def intsfromfile(f): 
    while True: 
     a = array.array('i') 
     a.fromstring(f.read(4000)) 
     if not a: 
      break 
     for x in a: 
      yield x 

スピードの理由からC++で同じことをやってください!私はマージする必要がある符号なし64ビット整数のソートされたリストを含む多くのファイルを持っています。ベクトルをマージするのにこの素敵なcodeという部分が見つかりました。

私は未知の長さのファイルのはifstreamは、ファイルの終わりに達するまで幸せに巡回できないベクトルとしての地位を提示するようにする方法で立ち往生しています。助言がありますか?私はistreambuf_iteratorで正しい木を吠えていますか?

+0

ファイル内の整数は、改行文字、スペースなどで区切られていますか?もしそうなら、 'istream_iterator'はあなたの友人です。 – Dawson

+0

@Toolboxは返事と解決策に感謝します!ファイルの形式は、セパレータなしの64ビットのリトルエンディアン符号なし整数です。だからistreambuf_iteratorのように見える方法ですか? istreambuf_iteratorをベクトルに変えるのを助けることができますか? – Donny

+0

何かを振り払って(そしてそれがコンパイルされていることを確認して)私にしばらくお待ちください。 – Dawson

答えて

7

ifstream(または実際には入力ストリーム)をイテレータのように動作する形式にするには、istream_iteratorまたはistreambuf_iteratorテンプレートクラスを使用します。前者は、書式設定が問題となるファイルに便利です。入力の書式設定を無視し、

#include <fstream> 
#include <vector> 
#include <iterator> // needed for istream_iterator 

using namespace std; 

int main(int argc, char** argv) 
{ 
    ifstream infile("my-file.txt"); 

    // It isn't customary to declare these as standalone variables, 
    // but see below for why it's necessary when working with 
    // initializing containers. 
    istream_iterator<int> infile_begin(infile); 
    istream_iterator<int> infile_end; 

    vector<int> my_ints(infile_begin, infile_end); 

    // You can also do stuff with the istream_iterator objects directly: 
    // Careful! If you run this program as is, this won't work because we 
    // used up the input stream already with the vector. 

    int total = 0; 
    while (infile_begin != infile_end) { 
     total += *infile_begin; 
     ++infile_begin; 
    } 

    return 0; 
} 

istreambuf_iteratorが通過読み取るために使用された時点で単一の文字をファイル:たとえば、次のように空白で区切られた整数の完全なファイルは、ベクトルのイテレータ範囲のコンストラクタに読み込むことができます。つまり、空白、改行文字などのすべての文字が返されます。アプリケーションによっては、それが適切かもしれません。

注:Scott Meyersはで有効なSTLを説明していますが、なぜ上記の別の変数宣言がistream_iteratorである必要がありますか。

ifstream infile("my-file.txt"); 
vector<int> my_ints(istream_iterator<int>(infile), istream_iterator<int>()); 

しかし、C++は実際に非常に奇妙な方法で、二行目を解析します。通常は、このような何かをするだろう。それはmy_intsという名前の関数の宣言とみなされ、2つのパラメータをとり、vector<int>を返します。最初のパラメータはタイプistream_iterator<int>であり、名前はinfileです(paranthesesは無視されます)。 2番目のパラメータは、名前がなく、引数がゼロの関数ポインタ(paranthesesのため)であり、タイプistream_iterator<int>のオブジェクトを返します。

あなたはそれを見ていない場合、かなりクールだけどかなり悪化します。私個人的にではなく、今

#include <fstream> 
#include <vector> 
#include <algorithm> 
#include <iterator> 

using namespace std; 

int main(int argc, char** argv) 
{ 
    ifstream input("my-file.txt"); 
    istreambuf_iterator<char> input_begin(input); 
    istreambuf_iterator<char> input_end; 

    // Fill a char vector with input file's contents: 
    vector<char> char_input(input_begin, input_end); 
    input.close(); 

    // Convert it to an array of unsigned long with a cast: 
    unsigned long* converted = reinterpret_cast<unsigned long*>(&char_input[0]); 
    size_t num_long_elements = char_input.size() * sizeof(char)/sizeof(unsigned long); 

    // Put that information into a vector: 
    vector<unsigned long> long_input(converted, converted + num_long_elements); 

    return 0; 
} 

:ここでEDIT


は、エンドツーエンドのレイアウトの64ビット数のファイルを読み込むことistreambuf_iteratorを使用した例です(reinterpret_castを使って、char_inputの配列を公開しています)、私はistreambuf_iteratorとよく似ていないので、64ビット文字よりもテンプレート化されたものを快適に使うことができません。はるかに簡単です。

+1

私は現在今日の投票ではなくなっていますが、残っていれば私はこれをアップヴォートします。 :-)これは優れた説明です。 – templatetypedef

+0

@templatetypedef心配しないで、私はそうではありません:P – wheaties

+1

IIRCパッシングのあいまいさを回避するために余分なカッコを追加する方法もありますが、これは醜いものであり、explicitnessで失敗します。 –