не удается прочитать все это в памяти при чтении с короткого счета - PullRequest
0 голосов
/ 10 июля 2019

В моем учебнике написано:

Read получает блок данных из потока в массив.Возвращает количество полученных байтов, которое всегда меньше или равно аргументу count.Если он меньше, чем count, это означает, что достигнут конец потока или поток предоставляет вам данные небольшими порциями (как это часто бывает в сетевых потоках).В любом случае баланс байтов в массиве останется не записанным, их прежние значения сохранятся.С помощью Read вы можете быть уверены, что достигли конца потока, только когда метод возвращает 0. Итак, если у вас есть поток длиной 1000 байт, следующий код может не прочитать все это в память:

// Assuming s is a stream:
byte[] data = new byte [1000];
s.Read (data, 0, data.Length);

Метод чтения может считывать от 1 до 1000 байтов, оставляя непрочитанный баланс потока.

Я в замешательстве и пишу простое заключениеприложение для проверки:

//read.txt only contains 3 chars: abc
using (FileStream s = new FileStream("read.txt", FileMode.Open))
{
   byte[] data = new byte[5];
   int num = s.Read(data, 0, data.Length);
   foreach (byte b in data)
   {
      Console.WriteLine(b);
   }
}

и вывод:

97

98

99

0

0

поэтому массив данных был записан, поэтому в учебнике сказано, что «остаток байтов в массиве останется не записанным, и он может не прочитать все это в память»,

РЕДАКТИРОВАТЬ: пожалуйста, откажитесь от моего предыдущего консольного приложения, реальный вопрос, который у меня возникает:

файл имеет 1000 байт, и я прошу прочитать все 1000 байтов:

byte[] data = new byte [1000];
s.Read (data, 0, data.Length);

почему он не может прочитать все это в память?и учебник также предоставляет правильный метод для чтения всех 1000 байтов:

byte[] data = new byte [1000];
int bytesRead = 0;
int chunkSize = 1;
while (bytesRead < data.Length && chunkSize > 0)
 bytesRead +=
 chunkSize = s.Read (data, bytesRead, data.Length - bytesRead);

Ответы [ 2 ]

1 голос
/ 10 июля 2019

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

Когда в тексте указано In either case, это относится к If it’s (the return value, i.e the bytes read from the stream) less than count.В этом случае считанные байты не занимают всю область буфера, которую вы указали для действия чтения.Остальная часть области буфера, конечно, остается нетронутой (remain unwritten, their previous values preserved).

В вашем случае это the end of the stream has been reached, потому что в вашем файловом потоке только 3 байта.Замыкающие нули в вашем массиве являются нетронутыми элементами буфера.

Итак, если у вас есть поток длиной 1000 байт, следующий код может не прочитать все это в память.

В тексте говорится о 1000-байтовом потоке, в то время как ваш поток содержит всего 3 байта.Для короткого файлового потока, который имеет только 3 байта, вполне вероятно, что все данные будут загружены в память одновременно, что вы и наблюдали.( просто «вероятно», а не «гарантировано» ).Для более длинного потока (или другого типа потока, например, NetworkStream) вам не гарантировано чтение байтов в количестве, достаточном для одновременного заполнения выделенной области буфера (есть вероятность, что вы можете получить только 1 байт за раз!).

1 голос
/ 10 июля 2019

В отношении:

byte[] data = new byte[5];
int num = s.Read(data, 0, data.Length);
foreach (byte b in data)

То, что foreach будет обрабатывать каждый байт в dataвсегда из пяти, независимо от того, сколько было записано при вызове Read()).

Количество байтов, фактически прочитанных вызовом Read(), сохраняется в переменной num, поэтому это то, что вы должны использовать для обработки ваших данных, что-то вроде (не проверено, но, вероятно, достаточно просто, чтобы этого не гарантировать):

for (int i = 0; i < num; i++) {
    Console.WriteLine(data[i]);
}

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

Если вы должны запустить этот цикл foreach до Read(), а также после, вы должны увидеть только первые три байта (если, конечно, предполагается, что содержимое файла отличается от того, что было в памяти) .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...