如何在fstream文件之间切换,而不关闭它们(同时输出文件) - C ++ [英] How can I switch between fstream files without closing them (Simultaneous output files) - 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 filebuf
s 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 implicitstd::flush
(like withstd::endl
). dummy
only exists to have anostream
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屋!