Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/3: Рейтинг темы: голосов - 3, средняя оценка - 4.67
Заблокирован

StreamReader отличие методов чтения Read и ReadBlock

21.08.2024, 15:16. Показов 906. Ответов 8

Студворк — интернет-сервис помощи студентам
В чем конкретно различие механизмов работы методов? Что именно блокируется в ReadBlock по сравнению с Read?
Читал, что блокирующий метод применяется в случае, если поступление данных в поток может задерживаться (сетевой поток) и т.п.
Из описания в док не понял чем конкретно методы отличаются.
Там написано про метод Read:
Этот метод возвращает значение после считывания количества символов, указанного count параметром, или достижения конца файла. ReadBlock — это блокирующая версия Read.
Про метод ReadBlock:
Метод блокируется до тех пор, пока не будут прочитаны символы count или не будет достигнут конец потока. Это блокирующая версия Read.
В первом случае используется термин "конец файла", во втором - "конец потока".
И как метод различает где конец файла, а где конец потока?
Если речь о чтении файла на ПК, то StreamReader сформирует поток на основе файла и тут нет никакой разницы между концом файла и концом потока. То есть, в этом случае явно нет никакого смысла в ReadBlock? Так?
А если StreamReader создаётся на основе другого потока, в котором могут быть задержки, то лучше (обязательно надо?) использовать ReadBlock?
ReadBlock проверяет в какой позиции находится исходя из Stream.Length и если не в последней, то ждёт окончания потока?
А у Read, что, другая логика?
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
21.08.2024, 15:16
Ответы с готовыми решениями:

Ошибка чтения int из файла через StreamReader.Read()
Неправильно и как-то непонятно считуются данные с текстового файла. Файл: 3 10 1 1 1 1 1 1 1 1 1 1 10 9 8 7 6 5 4 3 2 1 0 ...

StreamReader.ReadBlock - что нужно вставлять на месте char[] buffer
Дорогие друзья! Никак не могу понять, что же нужно вставлять на месте char buffer ?

В чем отличие read от read-line
Подскажите чем отличается read от read-line.

8
2393 / 1920 / 763
Регистрация: 27.07.2012
Сообщений: 5,561
21.08.2024, 15:46
Цитата Сообщение от titan4ik Посмотреть сообщение
В чем конкретно различие механизмов работы методов?
Насколько я понимаю, между ReadBlock и версии Read с теми же параметрами разницы нет никакой. Просто у Read ещё есть несколько перегрузок и асинхронная версия ReadAsync.
0
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
21.08.2024, 16:14
Лучший ответ Сообщение было отмечено titan4ik как решение

Решение

C#
1
2
3
4
5
6
7
8
9
10
11
12
// Blocking version of read.  Returns only when count
// characters have been read or the end of the file was reached.
//
public virtual int ReadBlock(char[] buffer, int index, int count)
{
    int i, n = 0;
    do
    {
        n += (i = Read(buffer, index + n, count - n));
    } while (i > 0 && n < count);
    return n;
}
Теперь немного на пальцах:
- у нас самый базовый Stream, поверх которого навесили StreamReader может возвращать через Read очень мелкими частями. Например если это NetworkStream с очень малым MTU и буфером, либо считываем очень большой кусок текста из файловой системы с малым кластером
- просто вызов Read вернет первый блок и завершит работу. Грубо говоря запросили 10к символов, записало первые 100 и вернуло только их.
- ReadBlock будет пытатья вычитать, пока не придет четко указанный count либо не поймем что дочитали до конца (внетренний Read вернет 0). Грубо говоря если в базовом потоке есть 10к символов, то мы таки их вычитаем все за один вызов.

Технически ReadBlock избавляет нас от необходимости самим писать обертку над чтением явно известных блоков по длине. Но это опасно зависанием чтения, в случае когда ожидаем блок длины N, но по факту приходит N минус k, и при этом внетренний Stream не сигнализирует об окончании потока (тот же NetworkStream).
2
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18286 / 14209 / 5368
Регистрация: 17.03.2014
Сообщений: 28,889
Записей в блоге: 1
21.08.2024, 16:21
Цитата Сообщение от titan4ik Посмотреть сообщение
В чем конкретно различие механизмов работы методов?
В том что Read может прочитать меньше count символов даже если конец потока еще не был достигнут. ReadBlock в этом случае всегда прочитает count символов.

Цитата Сообщение от titan4ik Посмотреть сообщение
Что именно блокируется в ReadBlock по сравнению с Read?
Под блокировкой имеется в виду что метод не возвращает управление в точку вызова.

Цитата Сообщение от titan4ik Посмотреть сообщение
В первом случае используется термин "конец файла", во втором - "конец потока".
И как метод различает где конец файла, а где конец потока?
В данном случае вместо "файла" должен быть "поток". Похоже разные люди в разное время писали документацию.

Цитата Сообщение от titan4ik Посмотреть сообщение
То есть, в этом случае явно нет никакого смысла в ReadBlock? Так?
Зависит от задачи.

Цитата Сообщение от titan4ik Посмотреть сообщение
А если StreamReader создаётся на основе другого потока, в котором могут быть задержки, то лучше (обязательно надо?) использовать ReadBlock?
Зависит от задачи.

Цитата Сообщение от titan4ik Посмотреть сообщение
ReadBlock проверяет в какой позиции находится исходя из Stream.Length и если не в последней, то ждёт окончания потока?
Надо смотреть исходники, но не думаю что он полагается на Length т.к. не каждый поток знает свою длину.

Добавлено через 20 секунд
Цитата Сообщение от John Prick Посмотреть сообщение
Просто у Read ещё есть несколько перегрузок и асинхронная версия ReadAsync.
У ReadBlock тоже есть Async вариант.
0
Заблокирован
21.08.2024, 16:37  [ТС]
Цитата Сообщение от Wolfdp Посмотреть сообщение
просто вызов Read вернет первый блок и завершит работу. Грубо говоря запросили 10к символов, записало первые 100 и вернуло
То есть, ReadBlock будет перезапускать метод Read, пока не прочитает требуемое число символов. Может так и зависнуть.
А Read прекращает свою работу (тоже код посмотрел, не думал.что он такой простой) как только символы заканчиваются (те, что в наличии уже). То есть поток ещё не закончен, а символы все прочитаны. И метод вернёт "-1". Понял.
Да, всё просто оказалось.
Спасибо, Wolfdp!
Выходит, что проще исходный код смотреть, чем в доки вчитываться и гуглить)
0
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
21.08.2024, 16:39
Цитата Сообщение от OwenGlendower Посмотреть сообщение
Под блокировкой имеется в виду что метод не возвращает управление в точку вызова.
Думаю это запутает. Оба метода блокирующие. Оба возвращают в точку вызова. Отличие только что ReadBlock под капотом вызывает Read, и потенциально не один раз.

Не по теме:

Цитата Сообщение от OwenGlendower Посмотреть сообщение
В данном случае вместо "файла" должен быть "поток". Похоже разные люди в разное время писали документацию.
Осмелюсь предположить что ReadBlock задумывался как метод чтения блоков из файлов, для облегчения рутинной работы. В итоге это и влепили в документацию, позабыв что технически там любой Stream можно подсунуть. И реально путает.



titan4ik,
Ради наглядности
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
using var r = new StreamReader(new BaseStream());
var buff = new char[16];
void Test(Func<char[], int, int, int> method)
{ 
    var sw = Stopwatch.StartNew();
    var count = method(buff, 0, buff.Length);
    sw.Stop();
    Console.WriteLine($"time: {sw.Elapsed}; count = {count}; result = {new string(buff)}");
}
Test(r.Read);
Test(r.ReadBlock);
;
 
class BaseStream : Stream
{
    private readonly byte[] _array = Encoding.ASCII.GetBytes("Nya!!");
    public override int Read(byte[] buffer, int offset, int count)
    {
        Thread.Sleep(TimeSpan.FromSeconds(1));
        var c = Math.Min(_array.Length, count);
        Array.Copy(_array, 0, buffer, offset, c);
        return c;
    }
 
    public override bool CanRead => true;
    public override bool CanSeek => false;
    public override bool CanWrite => false;
    public override long Length => throw new NotSupportedException();
    public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
 
    public override void Flush()
        => throw new NotSupportedException();
    public override long Seek(long offset, SeekOrigin origin)
        => throw new NotSupportedException();
    public override void SetLength(long value)
        => throw new NotSupportedException();
    public override void Write(byte[] buffer, int offset, int count)
        => throw new NotSupportedException();
}
Добавлено через 1 минуту

Не по теме:

Цитата Сообщение от titan4ik Посмотреть сообщение
Выходит, что проще исходный код смотреть, чем в доки вчитываться и гуглить)
Ситуативно. Документацию никогда не лишне глянуть.

1
Заблокирован
21.08.2024, 16:51  [ТС]
Цитата Сообщение от OwenGlendower Посмотреть сообщение
Надо смотреть исходники, но не думаю что он полагается на Length т.к. не каждый поток знает свою длину.
Да. Да.
Первое да - надо смотреть исходники (для уточнения и понимания документации, как в данном случае). Посмотрел и всё стало абсолютно прозрачно и определённо. А если бы ума хватило сразу глянуть, то и вопроса бы не было. Но удивило, что вопрос гуглился плохо. Было много объяснений и рассуждений, а код исходный никто не догадался привести)))
Второе да - не использует длину потока.

Добавлено через 6 минут
и для полноты инфы код метода Read
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 // Reads a block of characters. This method will read up to
 // count characters from this TextReader into the
 // buffer character array starting at position
 // index. Returns the actual number of characters read.
 //
 public virtual int Read(char[] buffer, int index, int count)
 {
     ArgumentNullException.ThrowIfNull(buffer);
 
     ArgumentOutOfRangeException.ThrowIfNegative(index);
     ArgumentOutOfRangeException.ThrowIfNegative(count);
     if (buffer.Length - index < count)
     {
         throw new ArgumentException(SR.Argument_InvalidOffLen);
     }
 
     int n;
     for (n = 0; n < count; n++)
     {
         int ch = Read();
         if (ch == -1) break;
         buffer[index + n] = (char)ch;
     }
 
     return n;
 }
Добавлено через 1 минуту
Цитата Сообщение от Wolfdp Посмотреть сообщение
Ради наглядности
Спасибо, но в этом коде ещё нужно разобраться. А так-то по своему вопросу я всё понял)
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,228
21.08.2024, 17:52
Цитата Сообщение от titan4ik Посмотреть сообщение
Выходит, что проще исходный код смотреть, чем в доки вчитываться и гуглить)
Ну да, это буквально source of truth.
0
Заблокирован
21.08.2024, 18:20  [ТС]
Цитата Сообщение от titan4ik Посмотреть сообщение
А так-то по своему вопросу я всё понял)
Нет, не понял.
В коде метода Read(char[] buffer, int index, int count) метод Read() ведь это просто возврат -1? Как же тогда это работает? Ведь цикл сразу завершится.
C#
1
2
3
4
5
6
7
8
9
// Reads the next character from the input stream. The returned value is
// -1 if no further characters are available.
//
// This default method simply returns -1.
//
public virtual int Read()
{
    return -1;
}
Добавлено через 20 минут
Это я запутался в исходниках. Это же исходники TextReader (абстрактный класс)
ОК. Понятно!)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
21.08.2024, 18:20
Помогаю со студенческими работами здесь

Переобразование StreamReader->Read() в тип int
здравствуйте, всем. Такой вопрос. Касается он с чтением с файла(.txt) с помощью потоков (StreamReader) . В общем, читаю я, как и...

Чем отличаются Peek и Read у StreamReader?
Чем отличаются Peek и Read у StreamReader?

После чтения StreamReader'ом, его методом ReadLine, вернуться к предыдущей строке
Кто-нибудь в курсе, реально ли после прочтения строки, вернуться на прошлую позицию. Вот смотрите пример: static void Main(string...

В чём отличие Read от ReadLn ?
В чём отличие Read от ReadLn ? Я раньше всегда писал Readln и даже не задумывался, чем эта функция отличается от Read. А тут писал...

отличие методов
Подскажите пожалуста в чем различее сортировки методом пузырька, от сортироки методом шелла?????


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 11.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru