5

オンラインでブラウジングしても解決できなかった小さな C++ の問題があります。これが私のコードです(抽出):

if(File.is_open()) {
    while(!File.eof())  {
        i++;
        getline(File,Line);
        if(i>=2) {                //Skip Headers
            int CharCount=0;
            for(int CharPosition=0; CharPosition<Line.size(); CharPosition++)                       {
                if(Line[CharPosition]==',') {
                    Length=CharPosition;
                    break;
                }
            }
            NameText=Line.substr(0,Length);
            Path= Path_Folder + "\\" + NameText + ".csv";
            if(!CheckExistance(Path.c_str())) {
                fstream Text_File;
            }
            Text_File.open(Path, fstream::in | fstream::out | fstream::app);
            Text_File<<Line<<"\n";
            Text_File.close();
        }
    }
}

Text_Fileこのコードは正常に動作していますが、while ループに入るたびに閉じるという事実を変更したいと思います。

基本的に、このプログラムは大きな入力ファイルを多数の小さなファイルに分割します。私の小さなファイルがどんどん大きくなるにつれて、実行はどんどん遅くなります(通常)。私の目標は、すべての小さなファイル ( Text_File) をこの while ループで開き、fstream ポインター (ポインター?) を別のものに切り替えることです。

私は次のように変更しようとしました:

...

NameText=Line.substr(0,Length);
Path= Path_Folder + "\\" + NameText + ".csv";

if(!CheckExistance(Path.c_str())) {
    fstream Text_File;
}

if(!Text_File.open()) {
    Text_File.open(Path, fstream::in |fstream::out | fstream::app);
}

Text_File<<Line<<"\n";
\\Text_File.close();

...

Text_Fileしかし、何があっても同じように取り組んでいNameTextます。Text_Fileしたがって、fstream のポインターは変更されないと推測しています。私は何をする必要がありますか?ポインタを休ませますか?どのように?

皆さん、ありがとうございました!

関連性があるかどうかはわかりませんが、Microsoft Visual C++ 2010 Express を使用しています。また、私は教育も生活もプログラマーではないので、高度な言葉を使わずに説明していただければ幸いです。

4

6 に答える 6

4

オブジェクトfilebufの sをジャグリングしたいようです。ostream

現在、唯一の障害は、それostreamまたはbasic_filebuf<char>コピー可能なタイプではないことです。したがって、それらを (ファイル名で) マップに直接配置することはできません。これは、小さなHolderタイプを作成することで簡単に回避できます。

struct Holder {
    Holder(std::string const& path) 
        : buf(std::make_shared<std::filebuf>())
    { 
        buf->open(path.c_str(), std::ios::out | std::ios::app);
    }
    std::shared_ptr<std::filebuf> buf;
};

std::map<std::string, Holder> buffers;

完全なプログラム (テスト済み) は次のようになります。

#include <fstream>
#include <sstream>
#include <iostream>
#include <map>
#include <memory>

const std::string Path_Folder = ".";

int main()
{
    std::istream& File     = std::cin; // just for example
    std::filebuf  dummy;
    std::ostream  TextFile(&dummy);

    struct Holder {
        Holder(std::string const& path) 
            : buf(std::make_shared<std::filebuf>())
        { 
            buf->open(path.c_str(), std::ios::out | std::ios::app);
        }
        std::shared_ptr<std::filebuf> buf;
    };

    std::map<std::string, Holder> buffers;
    int i = 0;

    std::string   Line;
    while(getline(File, Line))
    {
        if (i++<2)
            continue; //Skip Headers

        auto NameText = Line.substr(0, Line.find(','));
        auto Path = Path_Folder + '/' + NameText + ".csv";

        // open, only if not allready opened
        auto found = buffers.find(NameText);
        if (end(buffers) == found)
            found = buffers.insert({ NameText, Path }).first;

        TextFile.rdbuf(found->second.buf.get());

        TextFile << Line << std::endl; // notice implicit std::flush in std::endl
    }

    // all files are automatically closed here
}

さらに 3 つのメモ:

  • buffersマップが範囲外になると、ファイルは自動的に閉じられます。
  • このように切り替えるときに明示的なフラッシュを追加する必要があるかもしれrdbuf()ません.行を暗黙で終わらせない場合std::flush( with のようにstd::endl)。
  • dummyostreamバッファを切り替えることができるオブジェクトを持つためにのみ存在します

これを次の入力でテストしました。

Header Row #1
Header Row #2
Jack,1,some data
Jill,2,some more data
Jack,3,not reopening :)
Jill,4,jill still receiving output
Romeo,5,someone else reporting

これで、次の出力が得られました: See it live at Coliru

/tmp$ rm *.csv
/tmp$ make && ./test < input.txt && tail *.csv

g++ -std=c++11 -Wall -g test.cpp -o test
==> Jack.csv <==
Jack,1,some data
Jack,3,not reopening :)

==> Jill.csv <==
Jill,2,some more data
Jill,4,jill still receiving output

==> Romeo.csv <==
Romeo,5,someone else reporting
于 2013-07-28T23:09:38.170 に答える
0

すでに述べたように、存在チェックステートメントは効果がありません。おそらく、あなたの意図は次のようなことでした:

if(!CheckExistance(Path.c_str())) {
    fstream Text_File;

    Text_File.open(Path, fstream::in | fstream::out | fstream::app);
    Text_File<<Line<<"\n";
    Text_File.close();
}

if ステートメントのスコープ内の fstream は、外側のスコープにある必要があるものを非表示にします。また、close はオプションです。ストリームはスコープ外になると閉じられます。

于 2013-07-26T19:35:42.790 に答える
0

fstreamを再利用しようとしています。Text_Fileこれを行うにはclose()、csv ファイルへの書き込みが完了した後で、ストリームをフラッシュする必要があります。この質問を参照してください: C++ は fstream を再利用して複数のファイルを開いて書き込むことができますか?

また:この質問に対する私のGoogle検索は次のとおりです:http://goo.gl/Oy5KKM

于 2013-07-26T18:45:59.577 に答える