redirect stdout
От: Аноним  
Дата: 05.08.11 11:16
Оценка:
Привет!

Есть либа, в ней фунция save, сразу в файл, если имя файла не указанно, то на экран. Возможно ли создать редирект в строку?


#include <sstream>
..........................
std::ostringstream output( std::ostringstream::out );
std::cout.rdbuf(output.rdbuf());

x.save()


так не работает.
Re: redirect stdout
От: jazzer Россия Skype: enerjazzer
Дата: 05.08.11 11:21
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Привет!


А>Есть либа, в ней фунция save, сразу в файл, если имя файла не указанно, то на экран. Возможно ли создать редирект в строку?



А>
А>#include <sstream>
А>..........................
А>std::ostringstream output( std::ostringstream::out );
А>std::cout.rdbuf(output.rdbuf());

А>x.save()
А>


А>так не работает.


а в чем проблема с файлом? пусть скинет во временный файл, а ты потом загонишь его целиком в строку.
Я так думаю, эта операция по определению не скоростная...
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: redirect stdout
От: zaufi Земля  
Дата: 05.08.11 11:43
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Привет!


А>Есть либа, в ней фунция save, сразу в файл, если имя файла не указанно, то на экран. Возможно ли создать редирект в строку?


А>
А>#include <sstream>
А>..........................
А>std::ostringstream output( std::ostringstream::out );
А>std::cout.rdbuf(output.rdbuf());

А>x.save()
А>


А>так не работает.


т.к целевая платформа не указана... вот такой можно завертеть финт: создать FIFO, если либа принимает имя файла или pipe (`man 2 pipe`) если она хочет файловый дескриптор, пусть плюятся в в трубу... ну а с другой стороны читай и храни как хочешь. дело происходит на *nix'ах еси чо )
Re: redirect stdout
От: watch-maker  
Дата: 05.08.11 11:48
Оценка:
А>Есть либа, в ней фунция save, сразу в файл, если имя файла не указанно, то на экран. Возможно ли создать редирект в строку?

Возможно забить костыль с использованием pipes.
Собственно, всё просто: создаёшь pipe и один конец конец передаёшь функции, из другого читаешь строку.
Pipe можно создать именованным и передать в функцию save его имя, либо неименнованным, подменив на время дескриптор stdout на дескриптор pipe. Первый вариант чуточку сложнее, но более удобный, так как он не трогает глобальный stdout.
Единственная проблема с pipe состоит в том, что если объём записываемых данных велик, то при ненедлежащем использовании можно самому себе сделать deadlock. Впрочем, так же очевидно, что его можно надёжно избежать (простейший вариант — вычитывать содержимое pipe в другой нити чем вызываемая функция). Ну либо отказаться от pipe в пользу временных файлов — у них самоблокировок не будет.

А>
А>#include <sstream>
А>..........................
А>std::ostringstream output( std::ostringstream::out );
А>std::cout.rdbuf(output.rdbuf());

А>x.save()
А>


А>так не работает.


Записать в файл (и как частный случай, в stdout) можно десятком различных способов. Вполне ожидаемо, что манипуляции с std::cout никак не отобразятся на другой библиотеке, так как она просто может не использовать именно этот экземпляр std::cout для вывода.
Re[2]: redirect stdout
От: iking  
Дата: 05.08.11 16:32
Оценка:
Здравствуйте, jazzer, Вы писали:


J>а в чем проблема с файлом? пусть скинет во временный файл, а ты потом загонишь его целиком в строку.

J>Я так думаю, эта операция по определению не скоростная...

Проблемы нет.Старый проект разросся. Проект не мой с открытым кодом, но на некоторые либы исходники отсутствуют(.lib & .h). Сейчас программа обрабатывает вход соединение результатом которого является файл, который по шедуллеру отправляется на другой сервер, потом приходит файл с уд.сервера — опять в директорию, опять считывание содержимого и отсылка инициатору всей этой затеи... скорее всего изза возросшего кол-ва вход соединений все начало тормозить. Вот и хотел попробовать и все переделать. Писать свою либу не вариант там вшита гостовская криптозащита.
Re[2]: redirect stdout
От: iking  
Дата: 05.08.11 16:35
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>т.к целевая платформа не указана... вот такой можно завертеть финт: создать FIFO, если либа принимает имя файла или pipe (`man 2 pipe`) если она хочет файловый дескриптор, пусть плюятся в в трубу... ну а с другой стороны читай и храни как хочешь. дело происходит на *nix'ах еси чо )


Целевая ОС: Windows
Re[2]: redirect stdout
От: iking  
Дата: 05.08.11 16:50
Оценка:
Здравствуйте, watch-maker, Вы писали:

WM>Возможно забить костыль с использованием pipes.

WM>Собственно, всё просто: создаёшь pipe и один конец конец передаёшь функции, из другого читаешь строку.
WM>Pipe можно создать именованным и передать в функцию save его имя, либо неименнованным, подменив на время дескриптор stdout на дескриптор pipe. Первый вариант чуточку сложнее, но более удобный, так как он не трогает глобальный stdout.
WM>Единственная проблема с pipe состоит в том, что если объём записываемых данных велик, то при ненедлежащем использовании можно самому себе сделать deadlock.

Суть понятна, но я с pipe не работал — может посоветуете что можно почитать для результативного самообразования.

WM>Впрочем, так же очевидно, что его можно надёжно избежать (простейший вариант — вычитывать содержимое pipe в другой нити чем вызываемая функция).

Т.е. создать поток и читать с другой стороны канала?

WM>Ну либо отказаться от pipe в пользу временных файлов — у них самоблокировок не будет.

Я выше описал почему решил уйти от файлов.


WM>Записать в файл (и как частный случай, в stdout) можно десятком различных способов. Вполне ожидаемо, что манипуляции с std::cout никак не отобразятся на другой библиотеке, так как она просто может не использовать именно этот экземпляр std::cout для вывода.


Посмотрел файл .h либы, там вообщем если save без параметров то выполняется save(stdout), если с параметром то save(FILE* file)
Re[3]: redirect stdout
От: watch-maker  
Дата: 05.08.11 18:19
Оценка:
Здравствуйте, iking, Вы писали:

I>Суть понятна, но я с pipe не работал — может посоветуете что можно почитать для результативного самообразования.

Хоть мне и приходилось использовать именованые pipe под Windows, но учил я работу с ними в Unix. Так что можно, если сам не найдешь ничего, идею посмотреть в любой книге по межпроцессному взаимодействию, а уж детали реализации смотреть в MSDN.

WM>>Впрочем, так же очевидно, что его можно надёжно избежать (простейший вариант — вычитывать содержимое pipe в другой нити чем вызываемая функция).

I>Т.е. создать поток и читать с другой стороны канала?
Да. В pipe все данные хранятся в буферах в памяти. И если код выглядит так
1. создать-pipe()
2. записать-много-много-в-pipe()
3. прочитать-результат-из-pipe()
То если на шаге два буфер заполнится, то запись будет приостановлена до момента, пока в нём не появится место, но так как это может произойти только в пункте 3, то получаем блокировку.
Вынос пункта 3 в отдельный поток — простейший путь. Конечно, есть и другие варианты, но они требуют немного менять логику записи в пункте 2, что, как я понял, тебе не подходит.
Ну или, если известно, что размер записываемых данных заведомо меньше размера буфера, то можно в отдельный поток ничего не выносить.


WM>>Записать в файл (и как частный случай, в stdout) можно десятком различных способов. Вполне ожидаемо, что манипуляции с std::cout никак не отобразятся на другой библиотеке, так как она просто может не использовать именно этот экземпляр std::cout для вывода.


I>Посмотрел файл .h либы, там вообщем если save без параметров то выполняется save(stdout), если с параметром то save(FILE* file)


Ну так stdout ничего не знает о std::cout. Тут как раз std::cout использует stdout для вывода, а не наоборот. Попробуй его поменять.
А вообще, если у тебя в функцию передаётся не имя файла, а FILE*, то можно попробовать через него что-то упростить. В unix можно функцией fdopen сразу открыть неименованный pipe и получить нужный FILE* для работы. Так же есть функции open_memstream и fmemopen, которые открывают участок в памяти как FILE*, что делает решение всей задачи просто элементарным. К сожалению, в Windows аналога последних функций мне неизвестно, а вариант с fdopen возможно содержит какие-нибудь подводные камни, но, думаю, проверить его стоит.
Re[4]: redirect stdout
От: watch-maker  
Дата: 07.08.11 12:17
Оценка:
WM> В unix можно функцией fdopen сразу открыть неименованный pipe и получить нужный FILE* для работы.
Собственно, под msvc можно сделать аналогично, добавив немного магии с дескрипторами:
void immutableWriter(FILE* stream) {
    fprintf(stream, "I'm a immutable writer!\n");
}

std::string pipeProxy(void (*immutableWriter)(FILE*)) {
    HANDLE wPipe, rPipe;
    CreatePipe(&rPipe, &wPipe, NULL, 0);
    FILE* writer = _fdopen(_open_osfhandle((intptr_t)wPipe, _O_APPEND), "w");
    FILE* reader = _fdopen(_open_osfhandle((intptr_t)rPipe, _O_RDONLY), "r");
    immutableWriter(writer);
    fclose(writer);
    char buffer[8192];
    int readed = fread(buffer, 1, sizeof(buffer), reader);
    fclose(reader);
    return std::string(buffer, buffer + readed);
}


int main() {
    std::cout << pipeProxy(immutableWriter);
    return 0;
}
Разумеется, стоит обязательно добавить обработку ошибок.
Re[2]: redirect stdout
От: jazzer Россия Skype: enerjazzer
Дата: 08.08.11 01:49
Оценка:
Здравствуйте, watch-maker, Вы писали:

А>>Есть либа, в ней фунция save, сразу в файл, если имя файла не указанно, то на экран. Возможно ли создать редирект в строку?


WM>Единственная проблема с pipe состоит в том, что если объём записываемых данных велик, то при ненедлежащем использовании можно самому себе сделать deadlock.


Это не единственная проблема. Все зависит от того, как работает код записи. Если это просто набор write-ов по дескриптору — все нормально, но если там используется запись по позиции (к примеру, создается мегабайтный файл, забивается целиком нулями, потом 2-й килобайт заполняется неприличными словами), то пайпы, очевидно, не сработают.

Добрая половина юниксовых утилит, ожидающих файлы, не работает с именованными пайпами.


Но, вроде, здесь не этот случай.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: redirect stdout
От: fdn721  
Дата: 08.08.11 02:50
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Привет!


А>Есть либа, в ней фунция save, сразу в файл, если имя файла не указанно, то на экран. Возможно ли создать редирект в строку?



А>
А>#include <sstream>
А>..........................
А>std::ostringstream output( std::ostringstream::out );
А>std::cout.rdbuf(output.rdbuf());

А>x.save()
А>


А>так не работает.




FILE *stream = freopen( "freopen.out", "w", stdout );
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.