2009-10-27 2 views
6

Esiste un modo migliore per determinare la lunghezza di uno std :: istream al massimo i seguenti:Un modo migliore per determinare la lunghezza di un std :: istream?

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

sembra solo molto dispendioso di avere a cercare alla fine del flusso e poi cercare di nuovo all'originale posizione, soprattutto se il flusso potrebbe essere in un file su alcuni supporti lenti come un CD o un DVD.

+0

Perché hai bisogno della lunghezza? – sbi

+0

Un'API che sto utilizzando richiede la dimensione dei dati che sto trasmettendo. Utilizza un buffer di caratteri non elaborati e continua a elaborarli finché non raggiunge la fine del buffer. – FlintZA

+0

Si potrebbe usare 'stat()' sul file. Tuttavia, non è più veloce che cercare alla fine e cercare all'inizio, prima di leggere il contenuto ... ecco come vengono implementati i descrittori di file. Certo, 'stat()' non è C++ e richiede un nome file ... –

risposta

7

Il modo "migliore" è quello di evitare di dover lunghezza :)

  • Non tutti i flussi sono posizionabili (Ad esempio, immaginate un istream su una presa di rete)
  • Il tipo restituito da tellg() non è necessariamente numerico (l'unico requisito è che possa essere restituito a seekg() per tornare alla stessa posizione)
  • Anche se numerico, non è necessariamente un numero di byte. Ad esempio, potrebbe essere un valore "magico" che significa "alla fine"
  • Per fstreams, questioni come la cassa e la conversione linefeed possono rovinare tutto
+0

Mi rendo conto che aspettarsi che una lunghezza sia sempre disponibile è un po 'limitante per il tipo di flussi da utilizzare, per fortuna è molto improbabile che lo farò usare qualsiasi cosa diversa da ifstreams e le mie implementazioni di memstream e zipstream. – FlintZA

+0

Sembra che il tipo restituito da tellg() sia sempre numerico, basato su un [vincolo di std :: streampos] (http://stackoverflow.com/a/24437482/145173). –

-1

Avete preso in considerazione tenendo traccia della dimensione utilizzando istream :: gcount()?

+1

Ho bisogno della dimensione per l'allocazione del buffer su cui verranno copiati i dati, suppongo che potrei allocare un importo iniziale e un realloc in seguito, ma sono un po 'preoccupato per la frammentazione (lavorando in un ambiente limitato di mem). – FlintZA

-1

C'era una sorta di flusso che non riusciva a ottenere la lunghezza chiamando tellg(). In caso di, tellg() può restituire -1.

È possibile ottenere la lunghezza del flusso preparando un buffer di dimensioni sufficienti. Ho scoperto come ottenere la lunghezza esaminando la funzione 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); 

Sopra, Len è la dimensione reale dei dati in istream.