Введение в потоки ввода-вывода в C#
Поток передаёт байты по очереди: из программы наружу или снаружи в программу. У потока есть текущая позиция. Прочитали кусок - позиция сдвинулась вперёд. Записали - тоже.
Носитель может быть разным. Файл на диске, область в памяти и сетевое соединение снаружи не похожи, но программе от них нужно одно и то же: прочитать байты, записать байты и закрыть источник, когда он больше не нужен. Поэтому у них общий базовый тип, а конкретный носитель выбирают отдельно.
Поверх байтов уже читают текст или числа фиксированной длины. Текст требует кодировки, иначе те же байты станут другими буквами. Поток часто копит данные в буфере и обязан быть закрыт, иначе файл или соединение останутся заняты.