如何在fstream文件之间切换,而不关闭它们(同时输出文件) - C ++ [英] How can I switch between fstream files without closing them (Simultaneous output files) - C++

查看:323
本文介绍了如何在fstream文件之间切换,而不关闭它们(同时输出文件) - C ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个C ++问题,我无法通过在线浏览解决。这是我的代码(提取):

I have a little C++ issue that I couldn't solve by browsing online. Here is my code (extracted):

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();
        }
    }
}

这段代码工作正常,但是我想改变每次在while循环中关闭 Text_File 的事实。

This code is working fine, but I would like to change the fact that it closes the Text_File every time it goes in the while loop.

基本上,这个程序分割了一个大输入文件在很多较小的文件。随着我的
小文件越来越大,执行变得越来越慢
(正常)。我的目标是让所有较小的文件( Text_File )在
这个while循环中打开,只需将fstream指针(指针?)从一个切换到
另一个。

Basically, this program split a big input file in a lot of smaller files. As my smaller files get bigger and bigger, the execution gets slower and slower (normal). My goal is then to let all the smaller files (Text_File) opened in this while loop and just switch the fstream pointer (pointer?) from one to another.

我试图更改为:

...

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 是什么。所以我猜测,fstream Text_File 的指针不会改变。那么我需要什么呢?休息指针?如何?

But it is working on the same Text_File no matter what NameText is. So I am guessing that the pointer of the fstream Text_File doesn't change. What do I need to be then? Rest the pointer? How?

谢谢所有!

不确定是否相关,但我正在使用Microsoft Visual C ++ 2010年快递。
此外,我不是一个教育或生活的程序员,所以如果你可以解释它没有太高级的话,我会很感激。

Not sure it is relevant but I am working with Microsoft Visual C++ 2010 Express. In addition, I am not a programmer neither by education nor by living, so if you can explain it without too advanced words, I'll appreciate.

推荐答案

看起来你想在 ostream 上合并 filebuf 对象。

It looks like you would like to juggle the filebufs on an ostream object.

现在,唯一的障碍是 ostream basic_filebuf< char> / code>不是可复制类型,因此您不能直接将它们(通过文件名)放入映射。这很容易通过创建一个 Holder 类型来实现:

Now, the only obstacle is that ostream or basic_filebuf<char> aren't copyable types, so you can't put them into a map (by filename) directly. This is easily worked around by creating a little Holder type:

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;

现在完整的程序(测试)看起来像这样:

Now the complete program (tested) would look like this:

#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
}

另外三个附注:


  • buffers 地图超出范围。
  • 当您切换 rdbuf / code>像这样,如果你不用一个隐式的 std :: flush (如 std :: endl c> )。 $ 只有 ostream 对象,我们可以切换

  • 的缓冲区
  • files get automatically closed when the buffers map goes out of scope.
  • you might need to add explicit flushes when switching rdbuf() like this, if you don't end your lines with an implicit std::flush (like with std::endl).
  • dummy only exists to have an ostream object that we can switch the buffer of

我使用以下输入测试了这个:

I tested this with the following input:

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

现在,我得到以下输出: 住在Coliru

Now, I got the following output: 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

这篇关于如何在fstream文件之间切换,而不关闭它们(同时输出文件) - C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆