Что означает возвращаемое значение Filestream.Read?Как читать данные кусками и обрабатывать их? - PullRequest
3 голосов
/ 22 февраля 2011

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

Я думал об использовании чего-то вроде этого:

            byte[] data = new byte[30];
            int numBytesToRead = (int)fStream.Length;
            int offset = 0;

            //reading
            while (numBytesToRead > 0)
            {
                fStream.Read(data, offset, 30);
                offset += 30;
                numBytesToRead -= 30;

                //do something with the data
            }

Но я проверил документацию и их примеры, и они заявили, что возвращаемое значение вышеописанного метода чтения:

"Тип: System.Int32 Общее количество байтов, считанных в буфер. Это может быть меньше количества запрошенных байтов, если это число байтов в данный момент недоступно , или равно нулю, если достигнут конец потока. "

Что делаетэто означает, что они в настоящее время недоступны, может ли это произойти при чтении небольших объемов данных или это только для больших объемов?Если только для большого, то насколько приблизительно, потому что я буду читать также большими кусками в некоторых других местах.Если это может произойти в любое время, как мне изменить свой код, чтобы он по-прежнему работал эффективно?

Спасибо за ваше время и ответы.

Ответы [ 4 ]

5 голосов
/ 22 февраля 2011

Метод read возвращает количество возвращаемых байтов, которое может быть меньше количества запрошенных байтов.Обычно, когда вы читаете файл, вы получаете все запрошенные байты (если вы не достигли конца файла), однако, вы не можете рассчитывать на это всегда так.

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

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

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

byte[] data = new byte[30];
int numBytesToRead = (int)fStream.Length;
int offset = 0;

//reading
while (numBytesToRead > 0) {
  int len = fStream.Read(data, 0, data.Length);
  offset += len;
  numBytesToRead -= len;
  if (len == 0 && numBytesToRead > 0) {
    // error: unexpected end of file
  }
  //do something with the data (len bytes)
}
3 голосов
/ 22 февраля 2011

Попробуйте прочитать больше, чем доступно в файле. Вы можете сделать это в следующих двух сценариях:

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

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

Способ обработки двоичного файла в чанках выглядит следующим образом:

byte[] buffer = new byte[BUFFER_SIZE];
int inBuffer;
while ((inBuffer = stream.Read(buffer, 0, buffer.Length)) > 0)
{
    // here you have "inBytes" number of bytes in the buffer
}
1 голос
/ 22 февраля 2011

Байты, в настоящее время недоступные, применяются только к потокам, не относящимся к FileStream, таким как поток, найденный в HttpWebRequest.

FileStream.Read теоретически может вернуть 1 байт.Вы по-прежнему сможете обрабатывать такие небольшие пакеты.

Но он никогда не вернет 0, если не возникнет проблема, такая как потеря SMB-соединения, удаление файла, антивирус или попадание в конец файла.

Есть лучшие способы чтения файлов.Если вы имеете дело с текстовым файлом, попробуйте вместо этого использовать System.IO.StreamReader, поскольку он обрабатывает различную кодировку текста, разрывы строк и т. Д.

Также следует учитывать, что максимальный размер буфера составляет 2 ГБ, поэтомуне делай new buffer[fileStream.Length]

1 голос
/ 22 февраля 2011

FileStream происходит от Stream, а Stream - очень универсальный класс, а описание Read - из этого универсального класса.Поток также может быть, например, сетевым потоком, и там данные могут быть недоступны в настоящее время, поскольку они не были отправлены.Для FileStream вы можете предположить, что вы получите три типа возвращаемых значений:

  1. возвращаемое значение == количество считываемых байтов (последний параметр чтения): вы находитесь в серединефайла
  2. возвращаемое значение 0: Возможно, вы находитесь в конце файла или остальная часть потока просто недоступна.
  3. возвращаемое значение ==0: Вы уже прочитали весь контент.Больше нечего читать.
...