Підрозділ 18.5
BinaryReader та BinaryWriter. Бінарні потоки
18.5. BinaryReader та BinaryWriter. Бінарні потоки StreamReader / StreamWriter чудово підходять для текстових даних. Але медичні системи часто мають справу з даними зовсім іншої природи: показники датчиків — по
18.5. BinaryReader та BinaryWriter. Бінарні потоки
StreamReader/StreamWriter чудово підходять для текстових даних. Але медичні системи часто мають справу з даними зовсім іншої природи: показники датчиків — послідовності чисел з плаваючою комою, архіви кардіограм — тисячі 16-бітних відліків, медичні зображення — мільйони байтів з пікселями. Зберігати такі дані у текстовому форматі неефективно: рядок "98.6" займає 4 байти (символи), тоді як значення float 98.6f у бінарному форматі займає рівно 4 байти і зчитується без конвертації. Для роботи з типізованими бінарними даними C# надає BinaryWriter та BinaryReader.
BinaryWriter і BinaryReader — теж декоратори над Stream (як StreamWriter/StreamReader), але вони оперують не рядками, а C#-типами безпосередньо: int, double, bool, string, byte[]. Дані записуються у внутрішньому представленні .NET (little-endian для чисел) без будь-якого текстового кодування.


BinaryWriter — запис типізованих даних
Метод Write у BinaryWriter перевантажений для всіх примітивних типів C#: bool, byte, sbyte, char, short, ushort, int, uint, long, ulong, float, double, decimal, string, а також byte[] і char[]. Кожен тип записується у точній кількості байт свого розміру.
BinaryReader — читання типізованих даних
Критично важливо: порядок читання методами (ReadInt32, ReadString тощо) повинен точно відповідати порядку запису методами Write. Якщо порядок порушений — прочитаємо «сміття» або отримаємо виняток. Бінарний формат — це неявна схема даних, яку потрібно явно документувати.
BinaryReader — методи читання
| Тип C# | Метод BinaryReader | Розмір |
|---|---|---|
bool |
ReadBoolean() |
1 байт |
byte |
ReadByte() |
1 байт |
sbyte |
ReadSByte() |
1 байт |
char |
ReadChar() |
1–3 байти — за кодуванням BinaryWriter (UTF-8 за замовчуванням) |
short |
ReadInt16() |
2 байти |
ushort |
ReadUInt16() |
2 байти |
int |
ReadInt32() |
4 байти |
uint |
ReadUInt32() |
4 байти |
long |
ReadInt64() |
8 байт |
float |
ReadSingle() |
4 байти |
double |
ReadDouble() |
8 байт |
string |
ReadString() |
7-бітна довжина + байти |
byte[] |
ReadBytes(count) |
count байт |
Файл з фіксованими записами — індексований доступ
Бінарні файли з фіксованим розміром запису забезпечують O(1) доступ до будь-якого елемента через Seek:
Зверніть увагу на ширину поля імені. Попередня версія цього прикладу доповнювала ім'я пробілами до 20 символів (PadRight(20)) і копіювала перші 20 байтів UTF-8. Для латиниці це те саме, але кожна кирилична літера в UTF-8 займає 2 байти, тож «Петренко І.О.» (30 байтів) обрізалося до «Петренко І.», а розріз міг припасти навіть на середину літери. Правило для бінарних форматів: ширину текстового поля задають у байтах, з запасом на найдовше ім'я, а невикористані байти заповнюють нулями.
Практичний сценарій: бінарний архів ЕКГ
Реальний приклад застосування BinaryWriter/BinaryReader — зберігання даних електрокардіограми:

