IndexOutOfRangeException, когда поток кратен размеру буфера - PullRequest
0 голосов
/ 13 апреля 2010

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

Мой код начинается с чтения 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.

Ответы [ 2 ]

2 голосов
/ 13 апреля 2010

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

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

1 голос
/ 13 апреля 2010

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

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

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

...