2009-10-27 8 views
6

Есть ли лучший способ определить длину станда :: IStream, чем следующий:Лучший способ определить длину std :: istream?

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

Это только кажется, на самом деле расточительно должно стремиться к концу потока, а затем искать назад к оригиналу , особенно если поток может быть в файле на некоторых медленных носителях, таких как CD или DVD.

+0

Зачем вам нужна длина? – sbi

+0

API, который я использую, требует размера данных, которые я передаю. Он использует необработанный буфер символов и продолжает обрабатывать его до тех пор, пока он не достигнет конца буфера. – FlintZA

+0

Вы можете использовать 'stat()' в файле. Тем не менее, это не быстрее, чем поиск в конце и поиск в начале, прежде чем читать содержимое ... вот как реализуются файловые дескрипторы. Конечно, 'stat()' не является C++, и для этого требуется имя файла ... –

ответ

7

«Лучший» способ, чтобы избежать необходимости длины :)

  • Не все потоки доступные для поиска (например, представьте IStream на сетевую розетке)
  • Типа возвращаемого из tellg() не обязательно является числовым (единственное требование состоит в том, что его можно вернуть обратно в seekg(), чтобы вернуться в ту же позицию)
  • Даже если это числовое число, это не обязательно количество байтов. Например, это может быть «магическим» значение, означающее «в конце»
  • Для fstreams, такие вопросы, как дела и преобразование новой строки могут винт вещи
+0

Я действительно понимаю, что длина, которая всегда будет доступна, немного ограничивает использование потоков, к счастью, это очень маловероятно использовать что-нибудь другое, кроме ifstream, и мои собственные реализации memstream и zipstream. – FlintZA

+0

Похоже, что тип возвращаемого значения из tellg() всегда является числовым, основанным на [ограничении std :: streampos] (http://stackoverflow.com/a/24437482/145173). –

-1

Рассматривали ли вы отслеживание размера с помощью IStream :: gcount()?

+1

Мне нужен размер для выделения буфера, на который будут скопированы данные. Предположим, я мог бы выделить начальную сумму и realloc после этого, но меня немного беспокоит фрагментация (работа в ограниченной среде mem). – FlintZA

-1

Был какой-то поток, который не мог получить длину, позвонив по телефону tellg(). В случае, tellg() может вернуться -1.

Вы можете получить длину потока, подготовив буфер достаточного размера. Я узнал, как получить длину, посмотрев на функцию 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); 

Выше Len является реальный размер данных в istream.

Смежные вопросы