Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
c#_theoretical_2.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
750.08 Кб
Скачать

Двійковий ввід-вивід у файл

Для вводу-виводу у файл вбудованих у С# типів даних у їх двійковому представленні призначені класи потоків BinaryReader та BinaryWriter. При використанні цих потоків слід пам’ятати, що відповідні двійкові файли будуть містити дані в тому ж вигляді, в якому вони представлені в оперативній пам’яті, тобто у внутрішній двійковій формі представлення.

Класи BinaryReader та BinaryWriter є класами-оболочками (або просто оболочками) для класу FileStream. Клас-оболочка (wrapper class) деякого класу являє собою клас, який інкапсулює в собі екземпляр цього класу. Іншими словами: оболочка − це різновид класу-композита (див. тему «Композиція класів»). Як правило, оболочка класу містить тільки конструктори, в якості параметра яких виступає екземпляр класу.

Клас BinaryWriter є оболочкою деякого базового байтового потоку, який керує виводом двійкових даних. В цьому класі визначені методи, які призначені для запису даних всіх вбудованих у С# типів. Нижче наводяться найбільш важливі елементи класу BinaryWriter.

Елемент класу BinaryWriter

Призначення

public BinaryWriter(Stream output);

Найбільш часто уживаний конструктор класу. Параметр output визначає потік, у який виводяться дані. Для запису у вихідний файл у якості параметра output, як правило, використовують об’єкт класу FileStream. При цьому базовий потік output має бути створений у режимі доступу для запису. Якщо ж параметр output виявляється порожнім, то генерується виняткова ситуація ArgumentNullException. А якщо потік, заданий параметром output, не був відкритий для запису даних, то генерується виняткова ситуація ArgumentException.

public virtual Stream BaseStream { get; }

Повертає базовий потік, з яким працює об’єкт класу BinaryWriter.

public virtual void Close();

Закриває потік. При цьому закривається і базовий потік.

public virtual void Flush();

Очищає всі буфери даного потоку та записує дані цих буферів у відповідний файл.

public virtual long Seek(int offset, SeekOrigin origin);

Встановлює показчик у потоці на задану позицію. Ця позиція визначається зміщенням на offset байтів відносно значення параметра origin (SeekOrigin.Begin − початок потоку, SeekOrigin.Current − поточна позиція у потоці, SeekOrigin.End − кінець потоку).

Write

Ряд методів, які дозволяють записати у двійковий потік значення одного із вбудованих типів даних.

Клас BinaryReader також є оболочкою деякого базового байтового потоку, який керує вводом двійкових даних. В цьому класі визначені методи, які призначені для зчитування даних всіх вбудованих у С# типів. Нижче наводяться найбільш важливі елементи класу BinaryReader.

Елемент класу BinaryReader

Призначення

public BinaryReader(Stream input);

Найбільш часто уживаний конструктор класу. Параметр input визначає потік, у який вводяться дані із файлу. Як правило, у якості цього параметра використовують об’єкт класу FileStream. При цьому базовий потік input має бути створений у режимі доступу для читання. Якщо потік, заданий параметром input, не був відкритий для зчитування даних або з якихось інших причин, то генерується виняткова ситуація ArgumentException.

public virtual Stream BaseStream { get; }

Повертає базовий потік, з яким працює об’єкт класу BinaryReader.

public virtual void Close();

Закриває потік. При цьому закривається і базовий потік.

public virtual double ReadDouble();

public virtual int ReadInt32();

public virtual char ReadChar();

...

Ряд методів, які дозволяють зчитувати у двійковий потік значення одного із вбудованих типів даних.

Особливості роботи із двійковими потоками розглянемо на прикладі програмної реалізації наступної задачі.

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

class Program

{

public static void Example(string FileName)

{

try

{

// створюємо базовий потік

FileStream BaseStream = new FileStream(FileName, FileMode.Open);

// визначаємо кількість чисел у файлі через екземпляр базового потоку, оскільки

// двійковий потік властивості Length не має

long count = BaseStream.Length / 8;

// якщо файл не порожній

if (count > 0)

{

// створюємо двійковий потік для зчитування

BinaryReader br = new BinaryReader(BaseStream);

// змінна, в якій буде збережено номер позиції найменшого значення файлу

long pos = -1;

// змінна, в якій буде збережено найменше значення файлу

double minValue = double.MaxValue;

// масив, у який будуть зчитуватися дані із файлу

double[] a = new double[count];

// перебір значеньу файлі можна організувати, наприклад, так:

for (int i = 0; i < count; i++)

{

// зчитуємо чергове значення із файлу

double value = br.ReadDouble();

// записуємо зчитане значення у масив

a[i] = value;

// дивимось, чи не було прочитане менше значення, ніж до тепер

if (minValue > value)

{

minValue = value;

pos = i;

}

}

// закриваємо двійковий потік зчитування

br.Close();

// створюємо двійковий потік для запису

BinaryWriter bw = new BinaryWriter(new FileStream(FileName, FileMode.Open));

// встановлюємо показчик у потоці на мінімальне значення

bw.Seek((int)pos * 8, SeekOrigin.Begin);

// обнуляємо відповідне значення

bw.Write((double)0);

// закриваємо двійковий потік запису

bw.Close();

// відкриваємо новий двійковий потік зчитування

br = new BinaryReader(new FileStream(FileName, FileMode.Open));

// виводимо значення зміненого вихідного файлу на консоль

for (int i = 0; i < count; i++)

{

Console.Write(" " + br.ReadDouble());

}

// закриваємо двійковий потік зчитування

br.Close();

}

}

catch (Exception e)

{

Console.WriteLine("Помилка: " + e.Message);

}

}

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]