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

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

21.08.2024, 15:16. Показов 904. Ответов 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,560
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
18279 / 14202 / 5368
Регистрация: 17.03.2014
Сообщений: 28,883
Записей в блоге: 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
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru