Basicamente, estou procurando uma versão C ++ de fdopen (). Pesquisei um pouco sobre isso e é uma daquelas coisas que parece que deveria ser fácil, mas acaba sendo muito complicado. Estou perdendo algo nessa crença (ou seja, é realmente fácil)? Se não, existe uma boa biblioteca em algum lugar para lidar com isso?
EDIT: Mudei minha solução de exemplo para uma resposta separada.
c++
posix
fstream
file-descriptor
BD em Rivenhill
fonte
fonte
mmap
para o arquivo e expôs seu conteúdo como matriz de bytes.Respostas:
Da resposta de Éric Malenfant:
Com base nas observações acima e na minha pesquisa abaixo, há um código funcional em duas variantes; um para libstdc ++ e outro para Microsoft Visual C ++.
libstdc ++
Há um
__gnu_cxx::stdio_filebuf
modelo de classe não padrão que herdastd::basic_streambuf
e tem o seguinte construtorcom descrição Este construtor associa um buffer de fluxo de arquivo a um descritor de arquivo POSIX aberto.
Nós o criamos passando o identificador POSIX (linha 1) e então o passamos para o construtor do istream como basic_streambuf (linha 2):
Microsoft Visual C ++
Costumava haver uma versão não padrão do construtor do ifstream usando o descritor de arquivo POSIX, mas está faltando nos documentos atuais e no código. Há outra versão não padrão do construtor do ifstream pegando FILE *
e não está documentado (não consegui nem encontrar qualquer documentação antiga onde estivesse presente). Nós o chamamos (linha 1) com o parâmetro sendo o resultado da chamada _fdopen para obter o fluxo C FILE * do identificador de arquivo POSIX.
fonte
std::cout
implementação é uma boa ideia. Estou me perguntando qual é a diferença entrestdio_filebuf
estdio_sync_filebuf
?AFAIK, não há como fazer isso no C ++ padrão. Dependendo de sua plataforma, sua implementação da biblioteca padrão pode oferecer (como uma extensão não padrão) um construtor fstream tomando um descritor de arquivo (este é o caso de libstdc ++, IIRC) ou um
FILE*
como entrada.Outra alternativa seria usar um dispositivo boost :: iostreams :: file_descriptor , que você poderia envolver em um boost :: iostreams :: stream se desejar ter uma interface std :: stream para ele.
fonte
Há uma boa chance de seu compilador oferecer um construtor fstream baseado em FILE, embora não seja padrão. Por exemplo:
Mas, pelo que eu sei, não existe uma maneira portátil de fazer isso.
fonte
Parte da motivação original (não declarada) desta questão é ter a capacidade de passar dados entre programas ou entre duas partes de um programa de teste usando um arquivo temporário criado com segurança, mas tmpnam () lança um aviso no gcc, então eu queria para usar mkstemp () ao invés. Aqui está um programa de teste que escrevi com base na resposta dada por Éric Malenfant, mas usando mkstemp () em vez de fdopen (); isso funciona no meu sistema Ubuntu com bibliotecas Boost instaladas:
fonte
Na verdade, é muito fácil. Nicolai M. Josuttis lançou
fdstream
em conjunto com seu livro The C ++ Standard Library - A Tutorial and Reference . Você pode encontrar a implementação de 184 linhas aqui .fonte
Eu tentei a solução proposta acima para libstdc ++ por Piotr Dobrogost, e descobri que ela tinha uma falha dolorosa: devido à falta de um construtor de movimento adequado para istream, é muito difícil tirar o objeto istream recém-construído da função de criação . Outro problema com ele é que ele vaza um objeto FILE (mesmo que não seja o descritor de arquivo posix subjacente). Esta é uma solução alternativa que evita esses problemas:
A chamada para posix_fadvise () demonstra um uso potencial. Observe também que o exemplo usa static_assert e usando que são C ++ 11, além de que ele deve construir muito bem em C ++ 03 modo.
fonte
Meu entendimento é que não há associação com ponteiros de FILE ou descritores de arquivo no modelo de objeto iostream C ++ para manter o código portátil.
Dito isso, eu vi vários lugares se referindo aos mds-utils ou boost para ajudar a preencher essa lacuna.
fonte