2009-10-27 4 views
6

Y at-il une meilleure façon de déterminer la longueur d'un std :: istream que ce qui suit:Meilleur moyen de déterminer la longueur d'un std :: istream?

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

Il semble vraiment inutile d'avoir à chercher à la fin du cours d'eau et ensuite chercher à l'original position, en particulier si le flux peut être dans un fichier sur un support lent comme un CD ou un DVD.

+0

Pourquoi avez-vous besoin de la longueur? – sbi

+0

Une API que j'utilise nécessite la taille des données que je lui transmets. Il utilise un tampon de caractères brut et continue de le traiter jusqu'à ce qu'il atteigne la fin du tampon. – FlintZA

+0

Vous pouvez utiliser 'stat()' sur le fichier. Cependant, ce n'est pas plus rapide que de chercher à la fin et de chercher au début avant de lire le contenu ... c'est ainsi que les descripteurs de fichiers sont implémentés. Bien sûr, 'stat()' n'est pas en C++ et il faut un nom de fichier ... –

Répondre

7

La « meilleure » façon est d'éviter d'avoir la longueur :)

  • Pas tous les cours d'eau sont adressable (Par exemple, imaginez un istream sur une prise réseau)
  • Le type de retour de tellg() n'est pas nécessairement numérique (la seule exigence est qu'il peut être renvoyé à seekg() pour revenir à la même position)
  • Même s'il est numérique, il ne s'agit pas nécessairement d'un nombre d'octets. Par exemple, il pourrait être une valeur « magique » qui signifie « à la fin »
  • Pour fstreams, des questions comme le cas et la conversion de saut de ligne peut visser les choses
+0

Je me rends compte que l'attente d'une longueur pour toujours être disponible est un peu limitante au type de flux à utiliser, heureusement il est très improbable que je vais utiliser autre chose que ifstreams et mes propres implémentations memstream et zipstream. – FlintZA

+0

Il semble que le type de retour de tellg() soit toujours numérique, basé sur une [contrainte de std :: streampos] (http://stackoverflow.com/a/24437482/145173). –

-1

Avez-vous envisagé garder une trace de la taille en utilisant istream :: gcount()?

+1

J'ai besoin de la taille pour l'allocation du tampon à laquelle les données seront copiées - je suppose que je pourrais allouer une quantité initiale et realloc par la suite, mais je suis un peu inquiet de la fragmentation (travailler dans un environnement mem limité). – FlintZA

-1

Il y avait une sorte de flux qui ne pouvait pas obtenir la longueur en appelant tellg(). En cas de, tellg() peut renvoyer -1.

Vous pouvez obtenir la longueur du flux en préparant un tampon de taille suffisante. J'ai découvert comment obtenir la longueur en regardant la fonction 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); 

Au-dessus, est Len taille réelle des données dans istream.

Questions connexes