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

Тема 2 Файловий ввід-вивід Організація файлового вводу-виводу

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

Ввід-вивід у C# здійснюється за допомогою підсистеми вводу-виводу та класів бібліотеки .NET. Ми розглянемо обмін даними із файлами. Обмін даними реалізується за допомогою потоків.

Потік − абстрактне поняття, яке стосується будь-якого переносу даних від джерела до приймача. Потік визначається як послідовність байтів та не залежить від конкретного пристрою, з яким проводиться обмін (оперативна пам’ять, файл на диску, клавіатура або принтер).

Для підвищення швидкості передачі даних ввід-вивід здійснюється через спеціальну область оперативної пам’яті − буфер. Буфер виділяється окремо для кожного відкритого файлу. При записі у файл вся інформація спочатку направляється у буфер і там накопичується доти, поки весь буфер не заповниться. У цьому випадку або ж після спеціальної команди скидування відбувається передача даних на зовнішній пристрій. При читанні із файлу дані спочатку зчитуються у буфер, причому не стільки, скільки запитується, а скільки поміщається у буфер. Механізм буферизації дозволяє більш швидко та ефективно обмінюватись інформацією із зовнішніми пристроями.

Для підтримки потоків бібліотека .NET містить ієрархію класів, які визначені в просторі імен System.IO. Ці класи дозволяють працювати в різних режимах із файлами, каталогами та ділянками оперативної пам’яті.

Виконувати обмін даними із зовнішніми пристроями можна на рівні:

  • байтів (клас FileStream);

  • двійкового представлення даних (класи BinaryReader та BinaryWriter);

  • символів (класи StreamReader та StreamWriter).

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

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

Доступ до файлу може бути послідовним − коли наступний елемент можна прочитати (записати) тільки після аналогічної операції із попереднім елементом, або прямим − коли виконується читання (запис) довільного елемента за вказаною адресою. Символьні потоки дозволяють виконувати тільки послідовний доступ, у двійкових та байтових потоках можна використовувати обидва види доступів.

Робота із будь-якими файловими потоками у програмі передбачає наступні операції:

  1. Створення потоку та зв’язування його із фізичним файлом.

  2. Обмін (ввід-вивід).

  3. Закриття файлу.

Кожен клас файлових потоків містить декілька варіантів конструкторів, за допомогою яких, можна створювати об’єкти цих класів різними способами та в різних режимах.

Наприклад, файл можна відкрити тільки для читаня, тільки для запису або для читання і запису. Ці режими доступу до файлу містяться у переліку FileAccess простору імен System.IO.

public enum FileAccess {

Read = 1, // відкрити файл тільки для читання

Write = 2, // відкрити файл тільки для запису

ReadWrite = 3, // відкрити файл для читання і запису

}

Можливі режими відкриття файлу визначені у переліку FileMode.

[Serializable] [ComVisible(true)]

public enum FileMode

{

CreateNew = 1, // Вказує на те, що операційна система повинна створити новий файл.

// Якщо в каталозі вже існує файл з таким іменем, то виникає виняткова

// ситуація System.IO.IOException.

Create = 2, // Вказує на те, що операційна система повинна створити новий файл.

// Якщо в каталозі вже існує файл з таким іменем, то він буде знищений.

Open = 3, // Вказує на те, що операційна система повинна відкрити існуючий файл.

// Якщо в каталозі не існує даний файл, то виникає виняткова ситуація

// System.IO.FileNotFoundException.

OpenOrCreate = 4, // Вказує на те, що операційна система повинна відкрити файл, якщо він

// існує, інакше повинен бути створений новий файл з таким іменем.

Truncate = 5, // Вказує на те, що операційна система повинна відкрити існуючий файл.

// Після відкриття файл має бути обрізаний до нульової довжини.

Append = 6, // Вказує на те, що операційна система повинна у випадку, якщо файл існує −

// відкрити його та встановити показчик файлу у кінець цього файлу, якщо

// файлу з таким іменем не існує у каталозі, то створити новий. Цей режим

// можна використовувати тільки спільно із режимом доступу FileAccess.Write

}

Режими спільного використання файла різними користувачами визначає перелік FileShare.

public enum FileShare

{

None = 0, // Спільне використання відкритого файлу заборонено.

Read = 1, // Дозволяє відкривати файл для читання одночасно декільком користувачам.

Write = 2, // Дозволяє відкривати файл для запису одночасно декільком користувачам.

ReadWrite = 3, // Дозволяє відкривати файл для читання та запису одночасно декільком

// користувачам.

Delete = 4,

Inheritable = 16,

}

Як було відмічено на початку, файл на диску представляється у вигляді скінченної кількості послідовних байтів. У мові C# універсальне представлення послідовності байтів надає абстрактний клас Stream. Цей клас використовують всі інші класи потоків. Наведемо деякі із основних елементів цього класу:

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

Призначення

public abstract bool CanRead { get; }

Повертає значення true, якщо потік підтримує можливість читання, інакше − false.

public abstract bool CanSeek { get; }

Повертає значення true, якщо потік підтримує можливість прямого доступу, інакше − false.

public abstract bool CanWrite { get; }

Повертає значення true, якщо потік підтримує можливість запису, інакше − false.

public abstract long Length { get; }

Повертає довжину потоку у байтах.

public abstract long Position { get; set; }

Повертає поточну позицію показчика у потоці.

public void CopyTo(Stream destination);

Зчитує всі байти із поточного потоку та записує їх у потік, що задається параметром destination.

public abstract void Flush();

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

public abstract int Read(byte[] buffer, int offset, int count);

Зчитує послідовність байтів із поточного потоку та переміщає показчик у потоці на число зчитаних байтів. Після завершення виконання даного методу у масиві байтів buffer значення в інтервалі між offset і (offset + count-1) замінюються байтами, зчитаними із поточного джерела. Метод повертає загальну кількість байтів, зчитаних у buffer.

public virtual int ReadByte();

Повертає зчитаний байт із поточної позиції у потоці без знаку та переміщає позицію показчика у потоці на один байт вперед, або повертає -1, якщо досягнуто кінець потоку.

public abstract long Seek(long offset, SeekOrigin origin);

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

public abstract void Write(byte[] buffer, int offset, int count);

Записує послідовність count байтів із buffer у поточний потік та переміщає поточну позицію показчика в ньому вперед на число записаних байтів. Параметр offset задає зміщенння (від нуля) у buffer, з якого починається запис.

public virtual void WriteByte(byte value);

Записує байт value у поточну позицію у потоці та переміщає показчик у потоці на один бай вперед.

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