Используйте несколько потоков для записи в один выходной файл в C++
У меня урок Writer
это имеет два ofstream
члены.
Оба потока связаны с одним и тем же выходным файлом. Я хотел бы использовать оба потока в Writer::write
метод, но чтобы убедиться, что каждый поток записывает в конец реального выходного файла.
Код
class my_ofstream1:
public ofstream
{
// implement some functions.
// using internal, extended type of streambuf
};
class my_ofstream2:
public ofstream
{
// implement some functions.
// using internal, extended type of streambuf
// (not the same type as found in my_ofstream1)
};
class Writer
{
public:
void open(string path)
{
f1.open(path.c_str(),ios_base::out); f2.open(path.c_str(),ios_base::out);
}
void close()
{
f1.close(); f2.close();
}
void write()
{
string s1 = "some string 1";
string s2 = "some string 2";
f1.write(s1.c_str(), s1.size());
// TBD - ensure stream f2 writes to the end of the actual output file
assert(f1.tellp() == f2.tellp());
f2.write(s2.c_str(), s2.size());
}
private:
my_ofstream1 f1;
my_ofstream1 f2;
};
void main()
{
Writer w;
w.open("some_file.txt");
w.write();
w.close();
}
Вопросы
Как обеспечить f2
синхронизирован с f1
? это означает, что перед записью смещение потока f2
должен быть синхронизирован со смещением потока f1
и наоборот?
Я не могу использовать функцию std::ios::rdbuf, так как каждый ofstream
использует специальные производные streambuf
, так с помощью rdbuf()
Я потеряю необходимый функционал.
Я попытался использовать некоторые методы, описанные в разделе " Синхронизация потоков", но не смог этого сделать.
2 ответа
Похоже, что оба ваших класса используют идиому фильтрации streambuf. В любом случае, не выводите свои уроки из std::ofstream
, но прямо из ostream
и пусть они оба используют одно и то же std::filebuf
объект. Если вы используете идиому фильтрации streambuf, не позволяйте буферизировать ваш streambuf фильтрации; оставить это до финала std::filebuf
,
Другими словами, ваш "внутренний расширенный тип streambuf" должен содержать указатель на конечный приемник, который будет filebuf
(но ваши фильтрующие потоковые буферы не должны знать это). Функции как sync
они просто передаются в конечный пункт назначения, и им никогда не следует устанавливать буфер самостоятельно, а передавать все в filebuf.
Разве это не то, что вы ищете? Это может быть легко модифицировано для работы с ostream, а не с ofstream, что лучше - актуальная проблема - синхронизация буферов. В этом коде я просто сделал filebuf bf
небуферизованный и работает нормально. Или оставьте его в буфере, но включите звонки pubsync
при переключении между my_ofstream's. Я не понимаю почему ios:rdbuf
не доступен. Вы создаете свой собственный streambuf?
#include <iostream>
#include <fstream>
#include <assert.h>
using namespace std;
class my_ofstream1 : public ofstream
{
public:
my_ofstream1& write (const char_type* s, streamsize n)
{
ofstream::write (s, n);
//rdbuf()->pubsync();
return *this;
}
void attach (filebuf* bf){
ios::rdbuf(bf);
}
};
class my_ofstream2 : public ofstream
{
public:
my_ofstream2& write (const char_type* s, streamsize n)
{
ofstream::write (s, n);
//rdbuf()->pubsync();
return *this;
}
void attach (filebuf* bf){
ios::rdbuf(bf);
}
};
class Writer
{
filebuf bf;
my_ofstream1 f1;
my_ofstream1 f2;
public:
void open(string path)
{
bf.open(path.c_str(),ios_base::out);
bf.pubsetbuf(0,0); //unbufferred
f1.attach(&bf); f2.attach(&bf);
}
void close()
{
f1.close(); f2.close();
}
void write()
{
string s1 = "some string 1";
string s2 = "some string 2";
f1.write(s1.c_str(), s1.size());
assert(f1.tellp() == f2.tellp());
f2.write(s2.c_str(), s2.size());
}
};
int main()
{
Writer w;
w.open("some_file.txt");
w.write();
w.close();
return 0;
}