如何在不关闭它们的情况下切换fstream文件(同时输出文件) - C++

Vin*_*nce 5 c++

我有一点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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这段代码工作正常,但我想改变它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();

...
Run Code Online (Sandbox Code Playgroud)

Text_File无论是什么,它都在努力NameText.所以我猜测fstream的指针Text_File不会改变.那我需要做什么?把指针放在一边?怎么样?

谢谢你们!

不确定它是否相关,但我正在使用Microsoft Visual C++ 2010 Express.另外,我既不是教育也不是生活的程序员,所以如果你能用不太先进的词语来解释它,我会很感激.

seh*_*ehe 4

看起来您想filebuf在一个ostream物体上使用 s。

现在,唯一的障碍是ostreambasic_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;
Run Code Online (Sandbox Code Playgroud)

现在完整的程序(经过测试)将如下所示:

#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
}
Run Code Online (Sandbox Code Playgroud)

另外三点注意:

  • buffers当地图超出范围时,文件会自动关闭。
  • rdbuf()如果您不以隐式结束行std::flush(如 with ),则在像这样切换时可能需要添加显式刷新std::endl
  • dummy仅存在一个ostream可以切换缓冲区的对象

我使用以下输入对此进行了测试:

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
Run Code Online (Sandbox Code Playgroud)

现在,我得到以下输出: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
Run Code Online (Sandbox Code Playgroud)