FileStream.ReadByte - неэффективно - что это значит? - PullRequest
2 голосов
/ 22 октября 2010

Реализация по умолчанию в Stream создает новый однобайтовый массив и затем вызывает Read.Хотя это формально правильно, это неэффективно.Любой поток с внутренним буфером должен переопределить этот метод и предоставить гораздо более эффективную версию, которая считывает буфер напрямую, избегая дополнительного выделения массива при каждом вызове.документация:

http://msdn.microsoft.com/en-us/library/system.io.filestream.readbyte.aspx

Что это значит и как мне преодолеть эту неэффективность?

Ответы [ 5 ]

4 голосов
/ 22 октября 2010

Ну, смысл кажется достаточно ясным - и обходной путь просто не назвать ReadByte.

Не читайте по одному байту за раз - читайте в буфер соответствующего размера (я обычно беру около 8 КБ, но все, что примерно такого порядка, должно быть в порядке), используя Read(byte[], int, int) метод. Если после этого вам необходимо прочитать байты по отдельности, прочитайте их по одному из буфера.

Это становится проблемой, если вам нужно убедиться, что вы не читаете больше, чем предполагалось, если вы понимаете, что я имею в виду - например, если вы не собираетесь читать после первого 0 байт, потому что это означает, что это начало следующего «сообщения», и вы захотите прочитать его позже. В идеале, избегайте попадания в такую ​​ситуацию.

Упаковка FileStream в BufferedStream может помочь в этом случае, но я бы тщательно измерил производительность, если это важно ... и все же попытался бы избежать конструкций, которые требуют чтения одного байта в то время, если вы можете помочь.

3 голосов
/ 22 октября 2010

Это имеет значение, только если вы наследуете от Stream.При этом вы должны предоставить хотя бы метод Read, поверх которого в базовом классе реализован ReadByte.Это хорошо, но неэффективно, когда ваш поток способен получать отдельные байты напрямую - реализация по умолчанию затем сначала создаст однобайтовый буфер внутри, передаст его в ReadByte для его заполнения, а затем вернет один байт.Если вы можете реализовать свой буфер так, чтобы один байт мог быть возвращен напрямую, без выделения временного буфера, вы должны это сделать.чтобы сохранить их в буфере, Read часто более эффективен, чем ReadByte, даже когда вы читаете только один байт - но если вам действительно нужен только один байт, а используемая реализация потока обеспечивает оптимизированныйверсия, ReadByte на самом деле может быть быстрее.Если вы читаете отдельные байты для немедленной обработки, ReadByte вообще не должно быть проблемой - в конце концов, большинство стандартных потоковых классов уже буферизованы и должны обеспечивать оптимизированный ReadByte.В случае сомнений, профиль.

3 голосов
/ 22 октября 2010

Вам нужно использовать метод Read для чтения в буфер. Чтение одного байта не эффективно. Использование буфера:

  byte[] buffer = new byte[4096]; // 4K
  int bytesRead =0;
  while((bytesRead = stream.Read(buffer, 0, buffer.Length))>0)
  {
  // Do whatever with buffer
  }
2 голосов
/ 03 апреля 2018

Я не вижу проблемы в использовании FileStream ReadByte() метода.

Я думаю, что документация на самом деле сбивает с толку.

Метод ReadByte(), реализованный абстрактным классом Stream , неэффективен, поскольку он "создает новый однобайтовый массив и затем вызывает Read()".

Однако переопределенная версия ReadByte(), реализованная FileStream , прислушивается к совету этого предупреждения, читая внутренний буфер напрямую, как вы можете видеть в источнике здесь . Поэтому неясно, почему документация для FileStream ReadByte() содержит это предупреждение.

1 голос
/ 22 октября 2010

Я бы прочитал это как очень плохо написанный способ сказать «не используйте ReadByte () и используйте вместо него Read () ».Тем более что в документации для Read () написано

Этот метод переопределяет Read.

в разделе «Примечания».

...