2009-09-19 5 views
12

Tengo un bloque de memoria (opaco), que quiero almacenar en una Blob en mySQL a través de su adaptador C++. El adaptador espera una istream:inicializando un C++ std :: istringstream desde un buffer en la memoria?

virtual void setBlob(unsigned int parameterIndex, std::istream * blob) = 0; 

Así que mi pregunta es: ¿Cómo puedo crear un std :: istream de este bloque de memoria (a máquina como char *). No es una cadena ya que no tiene terminación nula (pero sé su duración, por supuesto).

No pude encontrar una manera de hacerlo sin copiar mi bloque de memoria, por ejemplo, en std :: string. Creo que esto es un poco derrochador Algo como esto no funciona:

std::streambuf istringbuf(blockPtr, blockLength); 
    std::istringstream tmp_blob(&istringbuf); 

porque std :: streambuf no tiene tal constructor. Vi la siguiente sugerencia.

std:: istringstream  tmp_blob; 
    tmp_blob.rdbuf()->pubsetbuf(blockPtr, blockLength); 

¿Es esa la forma correcta?

+0

duplicado Posible de [Ajuste del tampón interno utilizado por una corriente estándar (pubsetbuf)] (http://stackoverflow.com/questions/1494182/setting-the-internal-buffer- used-by-a-standard-stream-pubsetbuf) –

Respuesta

7

mirada a std :: istrstream que tiene un constructor

istrstream(char* pch, int nLength); 

Esta clase es una especie de depreciación o por lo menos que normalmente se les dice a utilizar otras clases.
El problema con strstream es que es más complejo administrar la memoria del búfer char *, por lo que en general preferiría stringstream como lo hace con la administración de memoria. Sin embargo, en este caso ya está administrando la memoria del char *, por lo que el beneficio normal es, en este caso, un costo. De hecho, en este caso, strstream hace exactamente lo que usted desea con una sobrecarga mínima en código o velocidad. Esto es similar a la discusión de ostrsteram by Herb Sutter

+5

Sí, pero Josuttis dice "Las clases de flujo char * se conservan solo por compatibilidad con versiones anteriores. Su interfaz es propensa a errores y rara vez se usan correctamente". Es por eso que era un poco reacio a usarlos. Y "retenido solo por compatibilidad con versiones anteriores" parece implicar que hay una manera mejor de usar clases "mejores". –

+0

Leí ese artículo, es directamente relevante. Gracias. Supongo que mi pregunta es respondida, aunque no hay comentarios sobre el "tmp_blob".rdbuf() -> pubsetbuf (blockPtr, blockLength); "approach. –

6

Boost.IOStreams tiene una secuencia que funciona como una cadena de caracteres, pero envuelve una matriz nativa, por lo que evita tener que copiar los datos.

std :: stringstream siempre crea su propio buffer interno

0

No comprobado pero quizás vale la pena una prueba ...

std::stringstream ss; 
ss.write(blockPtr, blockLength); 
ss.seekg(0); 

A continuación, llamar a esa función con setBlob ss. Todavía tienes ese búfer interno en std :: stringstream como jalf ya mencionado.

37

De hecho, es bastante trivial escribir std::streambuf one-shot que utiliza el búfer en su lugar ya que el comportamiento predeterminado de todas las funciones virtuales de std::streambuf hace 'lo correcto'. Puede simplemente setg leer el área en la construcción y underflow y uflow puede dejar de forma segura para devolver traits_type::eof() ya que el final de la zona de obtención inicial es el final de la secuencia.

por ejemplo:

#include <streambuf> 
#include <iostream> 
#include <istream> 
#include <ostream> 

struct OneShotReadBuf : public std::streambuf 
{ 
    OneShotReadBuf(char* s, std::size_t n) 
    { 
     setg(s, s, s + n); 
    } 
}; 

char hw[] = "Hello, World!\n"; 

int main() 
{ 
    // In this case disregard the null terminator 
    OneShotReadBuf osrb(hw, sizeof hw - 1); 
    std::istream istr(&osrb); 

    istr >> std::cout.rdbuf(); 
} 
+0

Jaja, su solución no apareció en los resultados de búsqueda cuando publiqué mi pregunta. Tenemos casi lo mismo;) http: // stackoverflow .com/questions/2079912/simpler-way-to-create-ac-memorystream-from-char-sizet-without-copying-th –

Cuestiones relacionadas