2009-10-27 15 views
6

¿Hay una mejor manera de determinar la longitud de un std :: istream que lo siguiente:¿Mejor forma de determinar la longitud de un std :: istream?

std::istream* pcStream = GetSomeStream(); 
pcStream->seekg(0, ios::end); 
unsigned int uiLength = pcStream->tellg(); 

Apenas se parece realmente un desperdicio tener que buscar hasta el final de la corriente y luego buscar nuevo a la original posición, especialmente si la transmisión puede ser a un archivo en algunos medios lentos como un CD o DVD.

+0

¿Por qué necesita la longitud? – sbi

+0

Una API que estoy usando requiere el tamaño de los datos que estoy pasando. Utiliza un búfer de caracteres sin formato y continúa procesándolo hasta que llega al final del búfer. – FlintZA

+0

Puede usar 'stat()' en el archivo. Sin embargo, no es más rápido que buscar al final y buscar al principio antes de leer los contenidos ... así es como se implementan los descriptores de archivos. Por supuesto, 'stat()' no es C++ y requiere un nombre de archivo ... –

Respuesta

7

La forma "mejor" es para evitar la necesidad de la longitud :)

  • No todos los flujos son seekable (Por ejemplo, imaginemos una istream en un socket de red)
  • El tipo de retorno de tellg() no es necesariamente numérico (el único requisito es que se puede pasar a seekg() para volver a la misma posición)
  • Aunque sea numérico, no es necesariamente un número de bytes. Por ejemplo, podría ser un valor "mágica" que significa "al final"
  • para fstreams, temas como el caso y la conversión de salto de línea se pueden enredar las cosas
+0

Me doy cuenta de que esperar que una duración siempre esté disponible es un poco limitante para el tipo de secuencias que se utilizarán, afortunadamente es muy poco probable que lo haga estar utilizando cualquier cosa que no sea ifstreams y mis propias implementaciones de flujo de datos y zipstream. – FlintZA

+0

Parece que el tipo de devolución de tellg() siempre es numérico, según una [constraint of std :: streampos] (http://stackoverflow.com/a/24437482/145173). –

-1

¿Ha pensado en hacer el seguimiento del tamaño mediante el uso de istream :: gcount()?

+1

Necesito el tamaño para la asignación del búfer al que se copiarán los datos; supongo que podría asignar una cantidad inicial y volver a hacerlo de nuevo, pero estoy un poco preocupado por la fragmentación (trabajando en un entorno de memoria limitada). – FlintZA

-1

Hubo algún tipo de flujo que no pudo obtener longitud llamando al tellg(). En caso de, tellg() puede devolver -1.

Puede obtener la longitud de la secuencia preparando un búfer de suficiente tamaño. Descubrí cómo obtener longitud mirando a la función stream::read.

const int DATA_SIZE = 1024 * 512; 
char buf[DATA_SIZE]; // 1024 * 512 is enough! 
std::istream& is = GetSomeStream(); 
int Len = is.rdbuf()->sgetn(buf, DATA_SIZE); 

arriba, Len es el tamaño de los datos reales en istream.

Cuestiones relacionadas