Как можно перегрузить streambuf для ofstream для модификации содержимого буфера при фактической записи содержимого в файл? В первую очередь интересует подпечатывание даты в начале новой строки, т.е. после выполнения операции:
s << "Some string\n" << "Another string\n" << flush;
В файле должно оказаться такое содержимое:
[Дата] Some string
[Дата] Another string
Перегрузить оператор << просьба не предлагать — так как один оператор << может записывать в буфер произвольное количество "\n".
Здравствуйте paul_shmakov, Вы писали:
PS>Как можно перегрузить streambuf для ofstream для модификации содержимого буфера при фактической записи содержимого в файл? В первую очередь интересует подпечатывание даты в начале новой строки, т.е. после выполнения операции:
Во-первых, классы не перегружаются :).
PS> s << "Some string\n" << "Another string\n" << flush;
PS>В файле должно оказаться такое содержимое:
PS>[Дата] Some string PS>[Дата] Another string
Надо написать свой класс, наследник от basic_streambuf; сначала содрать все из реализации std::basic_filebuf, потом найти в коде все fwrite и поменять их на свою функцию, которая будет сканировать буфер на предмет \n и писать его в файл, дописывая, что тебе над.
Написанный класс подсунуть в basic_ostream:
Можно для удобства сделать класс my_ofstream, по аналогии с std::basic_ofstream.
PS>Перегрузить оператор << просьба не предлагать — так как один оператор << может записывать в буфер произвольное количество "\n".
И что с того? Анализируй, сколько там ньюлайнов и вклинивайся, где надо.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте paul_shmakov, Вы писали:
PS>Как можно перегрузить streambuf для ofstream для модификации содержимого буфера при фактической записи содержимого в файл? В первую очередь интересует подпечатывание даты в начале новой строки, т.е. после выполнения операции:
PS> s << "Some string\n" << "Another string\n" << flush;
PS>В файле должно оказаться такое содержимое:
PS>[Дата] Some string PS>[Дата] Another string
Надо унаследовать свой класс, скажем LogBuf (;-)), от std::streambuf и подменить его метод overflow, реализовав в нем необходимую семантику. В данном случае эффективнее всего будет скопировать последовательность [pbase(); pptr()) в свою последовательность, вставляя "[Дата] " где нужно. Потом надо переадресовать вызов в std::filebuf::sputn(), дав в качестве аргументов параметры измененной последовательности:
Кроме того, для полнофункциональной работы твоего буфера надо будет переопределить функции underflow (если буфер предназначен для работы в режиме чтения), seekoff, seekpos (если хочешь, чтобы поток, проинициализированный твоим буфером поддерживал seek), sync и т.д., согласно документации.
Теперь осталось подменить потоку его буфер на твой. Если тебе не надо, чтобы поток был именно std::ofstream, просто передавай в конструктор std::ostream свой буфер, в противном случае надо будет вызывать std::ostream::rdbuf, передавая в качестве аргумента свой LogBuf.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте Павел Кузнецов, Вы писали:
ПК>Здравствуйте paul_shmakov, Вы писали:
PS>>Как можно перегрузить streambuf для ofstream для модификации содержимого буфера при фактической записи содержимого в файл? В первую очередь интересует подпечатывание даты в начале новой строки, т.е. после выполнения операции:
PS>> s << "Some string\n" << "Another string\n" << flush;
PS>>В файле должно оказаться такое содержимое:
PS>>[Дата] Some string PS>>[Дата] Another string
ПК>Надо унаследовать свой класс, скажем LogBuf (), от std::streambuf и подменить его метод overflow,
ПК>Кроме того, для полнофункциональной работы твоего буфера надо будет переопределить функции underflow (если буфер предназначен для работы в режиме чтения), seekoff, seekpos (если хочешь, чтобы поток, проинициализированный твоим буфером поддерживал seek), sync и т.д., согласно документации.
ПК>Теперь осталось подменить потоку его буфер на твой. Если тебе не надо, чтобы поток был именно std::ofstream, просто передавай в конструктор std::ostream свой буфер, в противном случае надо будет вызывать std::ostream::rdbuf, передавая в качестве аргумента свой LogBuf.
Первоначальное сообщение написал я, просто лень регистрироваться было. Буду разбираться, похоже на выход.
К сожалению, придется переползать на GCC 3.2 (и потерять совместимость с GCC 2.95), так как в старой библиотеке libstdc++ класс ofstream наследуется от fstreambase, в котором есть такие гадости:
Здравствуйте Sv2k, Вы писали:
S>К сожалению, придется переползать на GCC 3.2 (и потерять совместимость с GCC 2.95), так как в старой библиотеке libstdc++ класс ofstream наследуется от fstreambase, в котором есть такие гадости:
S>
S>Соответственно, вызывать std::ostream::rdbuf, передавая в качестве аргумента свой LogBuf нереально.
Надо вызывать не std::ofstream::rdbuf, которому, действительно, ничего передать нельзя, и который, действительно, так и должен быть определен, а std::ostream::rdbuf :