2009-10-27 10 views
6

Czy istnieje lepszy sposób określić długość std :: istream niż:Lepszy sposób określenia długości std :: istream?

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

tylko wydaje się naprawdę marnotrawny musiał szukać na końcu strumienia, a następnie starać się z powrotem do oryginału pozycja, szczególnie jeśli strumień może znajdować się w pliku na niektórych wolnych nośnikach, takich jak dysk CD lub DVD.

+0

Dlaczego potrzebujesz długości? – sbi

+0

Interfejs API, którego używam, wymaga rozmiaru danych, które przekazuję. Używa bufora znaków surowych i kontynuuje przetwarzanie, dopóki nie dotrze do końca bufora. – FlintZA

+0

Możesz użyć 'stat()' w pliku. Jednak nie jest to wcale szybsze niż szukanie na końcu i odszukanie na początku przed przeczytaniem zawartości ... tak właśnie zaimplementowano deskryptory plików. Oczywiście, 'stat()' nie jest C++ i wymaga nazwy pliku ... –

Odpowiedz

7

„Najlepsze” sposób jest uniknięcie konieczności długość :)

  • Nie wszystkie strumienie są możliwy do przeszukania (na przykład wyobrazić sobie istream na gniazda sieciowego)
  • Typ zwracany z tellg() nie jest koniecznie numeryczne (jedynym wymaganiem jest, że można go przekazać z powrotem do seekg(), aby powrócić do tej samej pozycji).
  • Nawet jeśli jest to numeryczne, niekoniecznie jest to liczba bajtów. Na przykład, może to być „magiczny” Wartość Znaczenie „na końcu”
  • Dla fstreams, kwestie takie jak sprawy i konwersji nowego wiersza można przykręcić rzeczy
+0

Rozumiem, że oczekiwanie, że długość zawsze będzie dostępna, jest trochę ograniczone do tego rodzaju strumieni, które będą używane, na szczęście jest to mało prawdopodobne, używaj czegokolwiek innego niż ifstream i mojego własnego wdrożenia memstream i zipstream. – FlintZA

+0

Wygląda na to, że typ zwracany przez tellg() jest zawsze numeryczny, na podstawie [ograniczenia std :: streampos] (http://stackoverflow.com/a/24437482/145173). –

-1

Czy za śledzenie wielkości za pomocą istream :: gcount()?

+1

Wymagam rozmiaru do przydzielenia bufora, do którego będą kopiowane dane - przypuszczam, że mógłbym przydzielić początkową kwotę i ponownie ją wykorzystać, ale jestem trochę zaniepokojony fragmentacją (praca w ograniczonym środowisku pamięci). – FlintZA

-1

Był jakiś strumień, który nie mógł uzyskać długości dzwoniąc pod numer tellg(). W przypadku, tellg() może zwrócić -1.

Możesz uzyskać długość strumienia, przygotowując odpowiedni rozmiar bufora. Dowiedziałem się, jak uzyskać długość, patrząc na funkcję 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); 

Powyżej Len jest prawdziwy rozmiar danych w istream.