IndexOutOfRangeException, когда поток кратен размеру буфера

У меня нет большого опыта работы с потоками и буферами, но мне нужно сделать это для проекта, и я застрял на исключении, которое генерируется, когда поток, который я читаю, кратен размеру буфера. Я выбрал. Позволь мне показать тебе:

Мой код начинается с чтения bufferSize (скажем, 100) байтов из потока:

numberOfBytesRead = DataReader.GetBytes(0, index, output, 0, bufferSize);

Затем я выполняю цикл while:

while (numberOfBytesRead == bufferSize)
{
     BufferWriter.Write(output);
     BufferWriter.Flush();
     index += bufferSize;
     numberOfBytesRead = DataReader.GetBytes(0, index, output, 0, bufferSize);
}

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

Но если bufferSize равен 100, а поток равен 200, мы будем читать позиции 0-99, 100-199, а затем пытаться считать ошибки 200-299. Я бы хотел, чтобы он вернул 0, но выдает ошибку. То, что я делаю, чтобы справиться с этим, это попытка поймать:

catch (System.IndexOutOfRangeException)
    numberOfBytesRead = 0;

... который завершает цикл и успешно завершает работу, но мы все знаем, что я не хочу контролировать поток кода с помощью обработки ошибок.

Есть ли лучший (более стандартный?) способ обработки чтения потока, когда длина потока неизвестна? Это кажется небольшим изъяном в довольно разумной стратегии чтения потоков, но я просто не знаю, ошибся ли я или что.

Специфика этого (который я немного подчистил для публикации) заключается в том, что MySqlDataReader попадает в столбец LARGEBLOB. Он работает, когда размер буфера больше, чем количество возвращаемых байтов, или когда количество возвращаемых байтов не кратно bufferSize. Потому что в этом случае мы не бросаем IndexOutOfRangeException.


person dnord    schedule 13.04.2010    source источник


Ответы (2)


Не уверен, что здесь есть настоящий вопрос. Но опубликованный код в корне неверен. Поток не обязан возвращать запрошенное количество байтов. Он может вернуть меньше, и часто так и происходит. Только когда он возвращает 0, вы точно знаете, что достигли конца потока.

Это позволяет потоку оптимизировать использование внутреннего буфера и повышает пропускную способность перекрывающихся операций ввода-вывода. NetworkStream — хороший пример.

person Hans Passant    schedule 13.04.2010
comment
Был, но я нашел ответ, и Хенк переместил ответ в вопрос, так что похоже, что его нет. Мой вопрос касается синтаксиса получения смещения 0, смещения 100, а затем смещения 200 в потоке, который имеет только 200. Получение смещения 200 вызывало исключение IndexOutOfRangeException вместо возврата 0. Может быть, это ошибка в MySqlDataReader? - person dnord; 14.04.2010

Вам не нужно быть в неведении относительно размера капли:

long blobSize = dr.GetBytes(0, 0, null, 0, 0);

... и затем, прежде чем читать, вы можете просто проверить, что index меньше, чем blobSize. Если это не так, вы знаете, что закрыли его и прочитали все, что можно было прочитать.

person dnord    schedule 13.04.2010