C # за допомогою потоків


116

Потоки для мене такі загадкові. Я не знаю, коли використовувати який потік і як ними користуватися. Чи може хтось пояснити мені, як використовуються потоки?

Якщо я правильно розумію, є три типи потоку:

  • stream
  • read stream
  • write stream

Це правильно? І, наприклад, яка різниця між a Memorystreamі a FileStream?


13
Ви можете перевірити stackoverflow.com/questions/507747 / ...
Preets

3
Візьміть масив байтів, а потім створіть для нього обгортку ( Stream), яка відкриває деякі корисні методи, такі як читання, запис і зміна позиції. Тепер ви можете створювати класи на основі їх резервного сховища (FileStream, MemoryStream), які успадковують Streamта будують цю функціональність на основі конкретного резервного магазину.
The Muffin Man

Відповіді:


80

Потік являє собою об'єкт , який використовується для передачі даних. Існує загальний клас потоків System.IO.Stream, з якого отримані всі інші класи потоків у .NET. StreamКлас має справу з байтами.

Класи конкретного потоку використовуються для обробки інших типів даних, ніж байти. Наприклад:

  • FileStreamКлас використовується , коли джерело зовні файл
  • MemoryStream використовується для зберігання даних у пам'яті
  • System.Net.Sockets.NetworkStream обробляє мережеві дані

Потоки читання / запису, такі як StreamReaderі StreamWriterне потоки - вони не походять із них System.IO.Stream, вони створені для того, щоб допомагати писати та читати дані з та передавати їх у потоки!


3
Отже, якщо я правильно розумію, потік містить дані і нічого з цим не робить. Читання "помічників" читача та письменника може обробляти (обробляти) дані в потоці?
Martijn

9
Ні, Stream не є контейнером даних, він використовує для передачі даних, наприклад FileStream передає дані з байтів [] у філософський файл, NetworkStream передає байт [] сокетом. Класи Reader Writer - це допоміжні класи для запису та читання з потоку, наприклад, StreamReader можна використовувати для читання з потокового потоку, а не в байті []. якщо ви дасте FileStream як параметр, він буде читатись з File, якщо NetworkStream з socket.
Арсен Мкртчян

крім того, StreamReader і StreamWriter призначені для читання та запису текстових потоків (текстових).
1c1cle

1
є хороша стаття, яка допоможе вам зрозуміти MemoryStream. codeproject.com/Articles/832387/…
Jiaji Li

2
@ user420667. Гарне питання. І у випадках AudioStream і TemperatureStream вони, швидше за все, будуть BinaryStreams для драйвера, який пов'язаний з пристроєм. Або ви можете створити CustomStream, створений спеціально для інтерфейсу.
1c1cle

62

Щоб трохи розширити тут інші відповіді та допомогти пояснити багато прикладу коду, про який ви побачите пунктир, більшу частину часу ви не читаєте і не записуєте в потік безпосередньо. Потоки - це засіб низького рівня для передачі даних.

Ви помітите, що функції читання та запису орієнтовані на байт, наприклад WriteByte (). Немає функцій для роботи з цілими числами, рядками і т. Д. Це робить потік дуже загального призначення, але менш простий у роботі, якщо, скажімо, ви просто хочете передати текст.

Однак .NET надає класи, які конвертують між рідними типами та інтерфейсом потоку низького рівня та передають дані в поток або з потоку для вас. Деякі помітні такі класи:

StreamWriter // Badly named. Should be TextWriter.
StreamReader // Badly named. Should be TextReader.
BinaryWriter
BinaryReader

Щоб скористатися ними, спочатку ви придбаєте свій потік, потім створіть один із перерахованих вище класів і пов'язуєте його з потоком. Напр

MemoryStream memoryStream = new MemoryStream();
StreamWriter myStreamWriter = new StreamWriter(memoryStream);

StreamReader і StreamWriter конвертують між нативними типами та їх рядковими поданнями, після чого передають рядки в потік і з нього у вигляді байтів. Так

myStreamWriter.Write(123);

запише "123" (три символи "1", "2", а потім "3") у потік. Якщо ви маєте справу з текстовими файлами (наприклад, html), StreamReader та StreamWriter - це класи, якими ви користуєтесь.

Тоді як

myBinaryWriter.Write(123);

запише чотири байти, що представляють 32-бітове ціле значення 123 (0x7B, 0x00, 0x00, 0x00). Якщо ви маєте справу з бінарними файлами або мережевими протоколами, ви можете використовувати BinaryReader і BinaryWriter. (Якщо ви обмінюєтесь даними з мережами чи іншими системами, вам потрібно пам’ятати про небезпеку , але це вже інша публікація.)


Класи адаптерів StreamWriter і Reader серйозно названі погано. Дякуємо, що згадали про це. Як же вони придумали це ім’я, як і раніше, мене дивують.
Тарік

Також погано названі навіть бінарні класи письменника та читача.
Тарік

22

Потоки хороші для роботи з великою кількістю даних. Коли завантажувати всі дані в пам’ять одночасно недоцільно, ви можете відкрити їх як потік і працювати з невеликими шматочками.


1
Хочеться побачити приклад того, що ви сказали щойно, "працюйте з невеликими шматочками цього".
Jenna Leaf

2
Потоки також корисні для невеликої кількості даних. Якщо програміст C # хоче маніпулювати вмістом файлу, він / він повинен використовувати потоки, незалежно від кількості даних. Це ж твердження справедливо і для мережевих потоків. Зрозуміло, що якщо програміст кодує мову нижчого рівня, як C, то можна записати символи або байти безпосередньо на диск або сокет, але навіть для невеликої кількості даних це забирає багато часу і більше схильне помилка.
1c1cle

10

Потік - це просто абстракція (або обгортка) над physicalпотоком байтів. Цей physicalпотік називається base stream. Таким чином , завжди є основний потік , по якому потік обгортка створюється і , таким чином , обгортка імені типу основного потоку тобто FileStream, і MemoryStreamт.д.

Перевага потокової обгортки полягає в тому, що ви отримуєте уніфікований api для взаємодії з потоками будь-якого базового типу usb, fileтощо.

Чому б ви ставилися до даних як до потоку - оскільки фрагменти даних завантажуються на вимогу, ми можемо перевірити / обробити їх як шматки, а не завантажувати цілі дані в пам'ять. Ось так більшість програм мають справу з великими файлами, наприклад, шифруючи файл зображення ОС.


4

Існує лише один базовий тип Stream. Однак за різних обставин деякі учасники викидають виняток, коли викликаються, оскільки в цьому контексті операція була недоступною.

Наприклад, a MemoryStream- це просто спосіб переміщення байтів в шматок пам'яті і з нього. Звідси ви можете зателефонувати на читання та запис.

З іншого боку, a FileStreamдозволяє читати або писати (або обидва) з / у файл. Чи можна насправді читати чи писати, залежить від того, як файл був відкритий. Ви не можете записати файл, якщо ви відкрили його лише для доступу для читання.


3

Я б почав з читання в потоках на MSDN: http://msdn.microsoft.com/en-us/library/system.io.stream.aspx

Memorystream та FileStream - це потоки, які використовуються для роботи із сирою пам'яттю та файлами відповідно ...


Дякуємо за посилання Мені подобалося, що "Ви можете переглядати вихідний код в Інтернеті, завантажити посилання для перегляду в режимі офлайн та переглядати джерела (включаючи патчі та оновлення) під час налагодження". Ця функція пропонує новий рівень розуміння.
Девід

1

Я б не називав такі різні потоки. Клас Stream має властивості CanRead та CanWrite, які повідомляють, чи можна читати та записувати певний потік.

Основна відмінність між різними класами потоків (наприклад, MemoryStream проти FileStream) полягає в сховищі резервних копій - звідки читаються дані або з яких вони записуються. Це щось очевидно з назви. MemoryStream зберігає дані лише в пам'яті, FileStream підтримується файлом на диску, NetworkStream зчитує дані з мережі тощо.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.