субота, 1 вересня 2012 р.

C#. Концепція та синтаксис. Частина 5


ЕЛЕМЕНТИ БІБЛІОТЕКИ КЛАСІВ .NET

Бібліотека класів .NET містить тисячі тисяч класів, інтерфейсів і переліків. Немає жодної змоги зробити вичерпний опис цих класів навіть у досить об'ємних публікаціях. Отож в процесі програмування в середовищі .NET необхідно мати електронний довідник.
У цьому розділі наведемо короткий огляд деяких методів окремих класів .NET, які здебільшого використовуються Windows- програмами.
Класи, інтерфейси та переліки в бібліотеці .NET згруповані у простори імен. У кожному з них зібрані засоби для виконання певних дій: інтерфейс застосувань Windows, робота з текстом, система безпеки та інших. Простори імен можуть містити інші простори імен, тобто мають деревовидну структуру.
Наведемо список деяких найкорисніших просторів імен:
Простір
імен
Опис
Microsoft.CSharp
Функції компілювання та генерування коду


мови C#.
Microsoft.Win3 2
Підтримка подій операційної системи та


системного реєстра.
System

Кореневий простір імен для більшості класів


бібліотеки. Містить також типи даних і базові


класи.
System.
.CodeDom
Представляє структуру документа з вихідним


кодом.
System.
. Collections
Словники, кеш-таблиці, черги, стеки.
System.
.ComponentModel
Реалізує поведінку компонент і керуючих


елементів під час виконання та під час


розробки програми.
System.
. Configuration
Програмний доступ до файлів .conf ig.
System.
Data
Класи, які реалізують технологію ADO.NET.
System.
. Diagnostics
Підтримка взаємодії з журналом подій,


системними процесами та лічильниками


продуктивності.
System.
. Directory-
Підтримка взаємодії зі службою Active
Services
Directoryo
System.
. Drawing
Класи, які реалізують графічні можливості


інтерфейсу GDI+.
System.
, Enterprise-
Підтримка взаємодії зі службами COM+.
Services

System.
, Globalization
Підтримка національних стандартів.
System.
. IO
Ввід та вивід для потоків і файлів.
System.
.Messaging
Підтримка черг подій.
System.
, Net
Підтримка мережевих протоколів.
System.
, Reflection
Доступ до метаданих, розташованих у


застосуваннях .NET.
System.
,Resources
Утворення та керування ресурсами.
System.
,Runtime
Підтримка різноманітних додаткових


можливостей загального оточення мов (CLR).
System.
, Security
Система безпеки середовища CLR.
System.
, ServiceProcess
Утворення та управління сервісами Windows.
System.
. Text
Підтримка роботи з текстом і стрічками.
System.
, Threading
Підтримка багатопотоковості.
System.
,Timers
Реалізація таймерів.
System.
, Web
Підтримка роботи через Web-браузер,


технології ASP.NET та web-сервісів.
System.
, Windows.Forms
Користувацький інтерфейс застосувань


Windows.
System.
, Xml
Підтримка мови XML та XML-стандартів.

Елементи простору імен можуть бути означені в різних файлах складених модулів.
Просторам імен можна надавати псевдоніми:
using Forms = System.Windows.Forms;
Глобальний простір імен має псевдонім global.
Щоб звернутися до простору імен з використанням його псевдоніма, використовують синтаксис alias : :. Наприклад:
Forms::Application.ExitThread() ;
Можлива ситуація, коли використовують різні складені модулі з однаковими просторами імен. Наприклад, назву StringLib використовують для позначення простору імен у складених модулях StringLibrary .dll та Str. dll:
Складений модуль StringLibrary . dll
namespace StringLib {
public class StrFunctions {
//функції роботи зі стрічками
}
}
Складений модуль Str.dll
namespace StringLib {
public class StrFunctions {
//функції роботи зі стрічками
}
}
При використанні цих двох складених модулів може виникнути конфлікт імен. Щоб уникнути такої неоднозначності, необхідно використати зовнішні аліаси:
extern alias StringLibrary; extern alias Str; // деякий код
StringLibrary.StringLib.StrFunctions.Method(); Str.StringLib.StrFunctions.Method() ;
Примітка. Специфікатори до псевдонімів і зовнішні аліаси доступні у .NET Framework версії 2.
Усі класи .NET є похідними від System. Object. Цей клас містить сім методів:


Метод Зміст

ToString Віртуальний метод, який повертає стрічкове представлення об'єкта.Зазвичай, перекривається класами-нащадками.

GetHashCode Віртуальний метод, який повертає кеш (hash) об'єкта для ефективного пошуку екземплярів класів у довідниках або кеш-таблицях (HashTable).

Equals Метод має дві версії: статичну та віртуальну. Перевіряє об'єкти на рівність.

ReferenceEquals Перевіряє на рівність два посилання

GetType Повертає об'єкт класу System.Туре (або нащадка цього класу) з інформацією про тип да них об'єкта.

MemberwiseClone Утворює коротку копію об'єкта: копіює в новий об'єкт дані типів за значенням і повертає посилання на цей об'єкт.

Finalize Метод виконує: роль деструктора. Викликається прибиральником „сміття" і може бути використаний для звільнення ресурсів.

Метод виконує роль деструктора. Викликається прибиральником „сміття" і може бути використаний для звільнення ресурсів.
Детальніше зупинимося на методах порівняння. Метод ReferenceEquals має сигнатуру public static bool ReferenceEquals(object objA, object objB);
і перевіряє, чи дві змінні (за посиланням) посилаються на один і той же екземпляр класу, чи ні. Якщо objA та objB містять посилання на одну адресу або обидва мають значення null, то метод повертає результат true. Віртуальну версію
public virtual bool Equals(object obj);
методу Equals використовують для конкретного екземпляра. Його реалізація в System.Object порівнює посилання. Проте цей метод призначений для випадку, коли потрібно перекрити його з метою порівняння даних об'єктів. Ми це вже робили в демонстраційному класі Point. Статична версія
public static bool Equals(object objA, object objB);
методу Equals працює аналогічно віртуальній. Метод перевіряє, чи не становить null одне чи обидва переданих йому посилання. Якщо так, то повертає значення false (одне посилання null) або true (обидва null). Якщо ж обидва посилання змістовні, то викликається віртуальна версія Equals.
Операція порівняння == порівнює посилання. Якщо потрібно порівнювати дані, то цю операцію необхідно перекрити (як це зроблено в класі Point) .
Розглянуті методи порівняння застосовуються до типів за посиланням. Типи за значенням також є похідними від ob ject. Не безпосередньо, а через клас System.ValueType. І у цьому класі вже перекритий метод Equals. Цей метод перевіряє вже не рівність посилань, а співпадіння даних у всіх полях структури.
Зазначимо, що метод ReferenceEquals для типів за значенням завжди повертає false.
Клас String
Ключове слово C# string насправді посилається на базовий клас .NET System. String. Наведемо деякі методи цього класу:
Метод
Зміст
Compare
Порівнює зміст стрічок з урахуванням регіональних

налаштувань
CompareOrdinal
Порівнює зміст стрічок без урахування регіональних

налаштувань
Format
Повертає стрічку, відформатовану відповідно до

переданого формату
IndexOf
Повертає індекс (починаючи з 0) першого входження

підстрічки у стрічці
IndexOfAny
Повертає індекс першого входження у стрічці

довільного символу із заданого масиву символів
LastIndexOf
Повертає індекс останнього входження підстрічки у

стрічці
LastIndexOfAny
Повертає індекс останнього входження у стрічці

довільного символу із заданого масиву символів
PadLeft
Вирівнює стрічку, додаючи декілька заданих символів

на початок стрічки
PadRight
Вирівнює стрічку, додаючи декілька заданих символів

наприкінці стрічки
Replace
Замінює деякий символ або підстрічку на інший символ

або під стрічку
Split
Розбиває стрічку на масив стрічок, використовуючи

заданий символ для визначення меж підстрічок
SubString
Повертає підстрічку заданої довжини, починаючи з

зазначеної позиції у стрічці
ToLower
Повертає копію стрічки, у якій всі символи переведені у

нижній регістр
ToUpper
Повертає копію стрічки, у якій всі символи переведені у

верхній регістр
Trim
Вилучає пробіли на початку й наприкінці стрічки
TrimEnd
Вилучає пробіли наприкінці стрічки
TrimStart
Вилучає пробіли на початку стрічки

Клас StringBuilder
Тип string ефективно зберігає стрічки. Якщо ми одній стрічковій змінній присвоїмо значення іншої, то насправді обидві змінні будуть посилатися на одну і ту ж ділянку пам'яті. Але при внесенні змін в одну з них виділиться нова ділянка пам'яті. Якщо ми спробуємо у циклі замінити кожен символ стрічки на якийсь інший, то таке копіювання у нові ділянки пам'яті відбудеться певну кількість разів, залежно від довжини стрічки.
Отож для маніпуляції зі стрічками доцільно використовувати інший клас представлення стрічок - System.Text. StringBuilder. Цей клас має декілька конструкторів:
StringBuilder sb1 = new
StringBuilder("стрічка", 10);
StringBuilder sb1 = new StringBuilder(10);
StringBuilder sb1 = new
StringBuilder("стрічка");
Перший конструктор виділяє пам'ять для розташування 10-ти символів та записує текст "стрічка". Другий - лише виділяє пам'ять. Третій - виділяє пам'ять за замовчуванням (зазвичай, удвічі більшу за потрібну) та записує текст.
Властивість Length повертає кількість значущих символів стрічки, а властивість Capacity - кількість зарезервованих символів.
Перелічимо основні методи класу StringBuilder:
Метод
Зміст
Append
Додає стрічку до поточної стрічки
AppendFormat
Додає стрічку, отриману з допомогою специфікатора формату
Insert
Вставляє підстрічку у поточну стрічку
Remove
Вилучає символи зі стрічки
Replace
Замінює деякий символ або підстрічку на інший символ або

під стрічку
ToString
Повертає стрічку, приведену до об'єкта String

Для роботи з інформацією про дату та час використовують структури System. DateTime і System. TimeSpan.
Структура DateTime має вісім перевантажених конструкторів, які надають зручний синтаксис для утворення екземплярів структури. Наприклад:
int year = 2005; int month = 5; int day = 8;
DateTime d1 = new DateTime (year, month, day) ;
int hour = 21;
int minute = 35;
int second = 20;
int milisecond = 120;
DateTime d2 = new DateTime(year, month, day, hour, minute, second, milisecond);
Конструктору DateTime можна передати (останнім параметром) об'єкт класу System.Globalization.Calendar. Існує декілька нащадків цього класу: GregorianCalendar, JulianCalendar та інші.
Структура TimeSpan призначена для представлення часових інтервалів. Ось приклади утворення екземплярів структури:
int hours = 10; int minutes = 15; int seconds = 30;
TimeSpan ts1 = new TimeSpan(hours, minutes,
seconds);
int days = 20;
TimeSpan ts2 = new TimeSpan(days,10,15,30);
long ticks = 776890;
TimeSpan ts3 = new TimeSpan(ticks);
Останній конструктор утворює часовий проміжок тривалістю 776890 тікіе (1 тік містить 100 наносекунд).
Структура DateTime має три статичні властивості, які відображають поточну дату та час, установлені на комп'ютері:
Властивість
Зміст

Now
повертає дату
та час
Today
повертає дату
(час - 0:00:00)
UtcNow
повертає дату
та час за Гринвічем

Наприклад,
DateTime today = DateTime.Today;
Решта властивостей відображає дату та час конкретного екземпляра структури:
Властивість
Зміст

Date
повертає дату (час - 0:00:00)

Day
повертає день місяця

DayOfWeek
повертає день тижня

DayOfYear
повертає номер дня в році

Hour
повертає годину

Minute
повертає хвилини

Second
повертає секунди

TimeOfDay
повертає екземпляр типу TimeSpan, який означає час,
що минув

від півночі

Year
повертає рік

Структура DateTime містить низку статичних
методів.
Зокрема:


Метод
Зм ст

DaysInMonth
повертає кількість днів у заданому місяці заданого року
IsLeapYear
повертає true, якщо вказаний рік є високосним

Parse,
перетворюють стрічкове значення дати та часу в
екземпляр
ParseExact
структури DateTime


Нестатичні методи маніпулюють значеннями дати та часу конкретного екземпляра і дозволяють додавати або віднімати часові інтервали, перетворювати дату та час у стрічкове представлення та інше.
Структура містить перевантажений метод ToString(), якому можна передавати стрічковий параметр з описом формату стрічки, у яку потрібно перетворити екземпляр структури. Існує значна кількість можливих форматів перетворення. Наприклад:
DateTime dt = new DateTime(); dt = DateTime.Now; string s;
s = dt.ToString("dd MMMM yyyy");
//08 травня 2005 s = dt.ToString("dddd, d-MMM-yy");
//неділя, 8-тра-05


s = dt.ToString("d.MM.yy H:mm:ss");
//8.05.05 9:08:20
Окрім цього, символи форматування використовують для надання різноманітних вбудованих форматів:
s = dt.ToString("d") ; //08.05.2005
s = dt.ToString("G"); //08.05.2005 1:25:38
Для ознайомлення зі всіма компонентами форматної стрічки для DateTime і вбудованих форматів дати та часу потрібно звернутися до довідкової системи.
Структура TimeSpan має 11 загальнодоступних властивостей. Властивості Days, Hours, Minutes, Seconds, Milliseconds та Ticks повертають ціле значення відповідно до кількості днів, годин, хвилин, секунд, мілісекунд і тіків в екземплярі структури. Властивості TotalDays, TotalHours, TotalMinutes, TotalSeconds, TotalMilliseconds повертають значення типу double, яке представляє тривалість екземпляра структури у відповідних одиницях.
Статичні методи FromDays, FromHours, FromMinutes, FromSeconds, FromMilliseconds, FromTicks дають змогу утворити новий екземпляр структури. Наприклад, код
TimeSpan tm = TimeSpan.FromDays(2.5);
повертає інтервал у два з половиною дні.
Метод Parse використовують для перетворення стрічкового представлення проміжку часу в еквівалентний екземпляр структури TimeSpan. Методу передається стрічковий параметр такого формату:
[-][d.]hh:mm:ss[.ff]
де d - кількість днів, hh - годин, mm - хвилин, ss - секунд, ff - часток секунди. Знак „мінус" задає від'ємний інтервал. Елементи в квадратних дужках не є обов' язкові.
Наступний код утворює екземпляр структури Time Span тривалістю два дні п'ять годин десять хвилин і 25,8750225 секунд:
TimeSpan tm = TimeSpan.Parse("2.5:10:25.8750225");
Над екземплярами структури TimeSpan можна виконувати операції додавання та віднімання:
TimeSpan tm1     = TimeSpan.FromDays(2);
TimeSpan tm2     = TimeSpan.FromDays(1);
tm1 += tm2;        //tm1 = 3 дні
tm2 -= tm1;         //tm2 = -2 дні
Ці ж дії можна виконати методами Add і Substract.
Операції множення часових інтервалів і множення часового інтервалу на число не означені.
Над екземплярами структур DateTime та TimeSpan можна виконувати операції додавання та віднімання з операндами таких типів:
Операція
Операнд 1
Операнд 2
Тип результату
+
DateTime
TimeSpan
DateTime
-
DateTime
TimeSpan
DateTime
-
DateTime
DateTime
TimeSpan

Наприклад:
DateTime dt1 = new DateTime(2005,1,1);
dt1 += TimeSpan.FromHours(45) ;
// 02.01.2005 21:00:00
DateTime dt2 = new DateTime(2006,1,1);
TimeSpan tm1 = dt2 - dt1; // 363.03:00:00
У просторі імен System.Collections міститься кілька класів, в екземплярах яких можна зберігати множину елементів, кількість яких може змінюватися під час виконання програми. Окрім цього, можна організувати доступ до елементів з використанням індексів, які не є цілими числами.
Динамічний масие може змінювати свій розмір у процесі додавання нових елементів. Динамічний масив реалізований у класі
ArrayList.
Наступний код містить приклади використання конструкторів класу ArrayList:
ArrayList ar = new ArrayList();
ArrayList ar10 = new ArrayList(10);
ArrayList arar = new ArrayList(ar);
Перший конструктор утворює масив, місткість якого 0. Місткість - це максимальна кількість елементів, яку може зберігати масив без перебудови.
Другий конструктор утворює масив, місткість якого 10. Окрім конструктора, задавати (і отримувати) місткість можна з допомогою властивості Capacity.
Третій конструктор утворює масив arar, який є копією масиву ar.
Для додавання елементів в об'єкт ArrayList використовують метод Add:
ar.Add("Ue елемент динамічного масиву");
Нумерація елементів починається з нуля. Кількість елементів у масиві відображає властивість Count:
for (int i=0; i < ar.Count; i++)
Console.WriteLine(ar[i].ToString());
Якщо місткість масиву дорівнює кількості доданих елементів, то при додаванні нового елемента масив перебудовується з метою збільшення місткості. Цей процес не можна назвати ефективним, тому краще зарезервувати достатню місткість масиву. Загалом, швидкодія роботи динамічних масивів у декілька разів менша порівняно зі звичайними масивами. Отож при нагоді краще використовувати звичайні масиви.
Елементи масиву можуть мати довільний тип, оскільки вони зберігаються як об'єкти класу System. Object.
Для додавання або вставляння елементів використовують методи
int Add(value),
void Insert(index, value) ,
void AddRange(collection),
void InsertRange(index, collection),
void SetRange(index, collection).
Наприклад:
ar.Add(new Point(1, 1)); ar.Insert(0,new Point(2, 1)); string[] strs = {"елементи", "для", "Range"};
ar.AddRange(strs) ; ar.SetRange(3,strs) ;
Метод Add додає елемент наприкінці списку. Метод Insert вставляє елемент у середину списку, посуваючи всі елементи з індексами, не меншими за index.
Методи AddRange та InsertRange використовують для додавання або вставляння діапазону елементів. Цей діапазон задається колекцією (наприклад, масивом).
Метод SetRange не вставляє діапазон елементів, а замінює ними інші, починаючи із заданого індексу.
Для вилучення елементів з динамічного масиву використовують методи
void RemoveAt(index) , void Remove(value) ,
void RemoveRange(startlndex, collection).
Пошук елементів у динамічному масиві здійснюють такими методами:
bool Contains(value),
int IndexOf(value [,startIndex [, count]]), int LastIndexOf(value [,startIndex [, count]]), int BinarySearch(value [, comparer]), int BinarySearch(index,count,value,comparer) .
Метод Contains повертає true, якщо динамічний масив містить хоча б один елемент зі значенням value.
Методи IndexOf і LastlndexOf повертають позицію, відповідно, першого та останнього елемента зі значенням value. Необов'язкові параметри startlndex і count локалізують область пошуку.
Метод BinarySearch застосовують для пошуку елемента value у відсортованому масиві. Параметри index та count локалізують область пошуку. Параметр comparer задає правило порівняння об'єктів. Об'єкт comparer - це екземпляр деякого класу, який підтримує інтерфейс IComparer і реалізує метод IComparer.Compare. Об'єкт comparer можна використовувати й у методах сортування: void Sort([comparer]), void Sort(index, count, comparer), void Reverse([index, count]).
Метод Sort впорядковує елементи динамічного масиву за заданим об'єктом comparer правилом порівняння. Якщо параметр comparer відсутній або має значення null, то числа та дати впорядковуються за зростанням, а символи - за абеткою в порядку зростання. Метод Reverse використовують для зміни порядку елементів на протилежний.
Як і всі колекції, клас ArrayList реалізує інтерфейс IEnumerable, отож для поелементної ітерації екземпляра цього класу можна використовувати цикл foreach.
Бітоеий масив - це масив булевих значень. Кожне булеве значення у такому масиві представляється єдиним бітом (0 або 1). Збереження одного біта вимагає менше пам'яті, ніж збереження значення типу bool. Як і інші колекції, бітовий масив є динамічним.
Бітовий масив реалізований у класі BitArray, який має декілька конструкторів:
BitArray (length [, defaultValue]) , BitArray (values), BitArray (bits).
Тут length - місткість масиву, а defaultValue - значення, яким потрібно заповнити елементи масиву при утворенні.
Параметр values може бути масивом елементів типу bool, byte або int. Відповідний конструктор утворить бітовий масив з місткістю, яка відповідає довжині масиву-аргумента. Елементи набудуть значення false, якщо відповідний елемент аргумента містить значення 0 або false. У протилежному випадку ці значення будуть true.
Останній конструктор - це конструктор копій. Тут bits - бітовий масив.
Як і для звичайного масиву, доступ до елементів бітового масиву здійснюється з допомогою індексів:
BitArray bitAr = new BitArray(10);
bitAr[0] = false;
Кількість елементів у масиві показує властивість Count. Значення цієї властивості завжди збігається зі значенням властивості Length. Відмінність між ними в тому, що Count є властивістю лише для читання.
Клас BitArray має декілька корисних методів.
Методи And, Or та Xor виконують, відповідно, операції І, АБО та виключне І між елементами поточного бітового масиву та відповідними елементами бітового масиву-аргумента.
Метод Not інвертує всі значення елементів масиву.
Метод CopyTo копіює елементи з бітового масиву в одномірний масив.
Кеш-таблиця дає змогу зберігати пари ключ - значення. Ключ у кеш-таблиці можна використовувати для пошуку відповідного йому значення. Як ключ, так і значення можуть бути довільного типу.
Кеш-таблиця реалізована в класі Hashtable. Цей клас належить до множини словників, тобто класів, які підтримують інтерфейс IDictionary.
Клас Hashtable містить одинадцять конструкторів. Найпростіші з них мають сигнатуру
Hashtable ([capacity [,loadFactor]]);
Розглянемо простий приклад:
Hashtable ht = new Hashtable(7);
ht.Add("Point_1", new Point());
Point p = (Point)ht["Point_1"];
Конструктор Hashtable( capacity) використовують найчастіше. Словники найефективніше працюють, коли їх місткість capacity є простим числом. Це спричинено специфікою алгоритмів, які використовуються у словниках.
Додають об'єкти в Hashtable з допомогою методу Add:
void Add(£ey, value);
де обидва параметри мають тип object. Зауважимо, що словники не мають індексів таких, як масиви. Тому методів типу Insert також мати не можуть.
Доступ до значення здійснюється з допомогою ключа у квадратних дужках. Оскільки значення повертається як об' єкт типу object, потрібне           явне            приведення            типу:
(Point)ht["Point_____ 1" ].
Якщо ключем слугує клас користувача, то в ньому має бути реалізовано алгоритм кеш. Ця реалізація, розташована в перекритому методі GetHashCode, передбачає виконання таких умов:
         алгоритм повинен бути швидким;
         якщо A.Equals(B) дорівнює true, то методи A.GetHashCode() та B.GetHashCode() повинні завжди повертати ідентичний кеш;
         в ідеалі алгоритм повинен видавати значення, рівномірно розподілені між int. MinValue та int. MaxValue.
Остання вимога спричинена потребою розташування поруч об'єктів, для яких кеш дає ідентичний індекс. У цьому випадку бажано, щоб місткість словника була значно більшою за кількість
розташованих у ньому елементів. Пропорція між заповненою та незаповненою частинами таблиці характеризується коефіцієнтом завантаження - loadFactor. За меншого максимального завантаження ефективніше працюватиме кеш-таблиця, проте пам'яті вона займатиме більше.
Простий приклад перекриття методу GetHashCode ми вже навели, розглядаючи перевантаження операцій на прикладі демонстраційного класу Point, де неявно використали кеш Microsoft для стрічкового типу:
public override int GetHashCode()
{
return ToString().GetHashCode();
}
Властивість Count повертає кількість елементів, які зберігаються в таблиці.
Властивість Keys повертає колекцію (інтерфейс ICollection), яка містить ключі таблиці.
Властивість Values повертає колекцію, яка містить значення таблиці.
Серед методів класу Hashtable зазначимо такі:
Метод
Зміст
Add
Додає елемент із заданим ключем і значенням
Clear
Вилучає всі елементи з таблиці
Clone
Утворює копію таблиці
Contains
Визначають, чи містить таблиця заданий ключ
ContainsKey

ContainsValue
Визначає, чи містить таблиця задане значення
Remove
Вилучає з таблиці елемент із заданим ключем

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


Відсортований список реалізований у класі SortedList. Клас містить шість конструкторів, з яких найчастіше використовують такий:
SortedList ([capacity]);
Зм ст
Властивості і більшість методів класу SortedList такі ж, як і в класу Hashtable. Зі специфічних методів зазначимо такі:
Метод
GetBylndex                Повертає значення на заданій позиції у списку
GetKey                        Повертає ключ на заданій позиції у списку
GetKeyList                Повертає інтерфейс IList зі всіма ключами списку
GetValueList             Повертає інтерфейс IList зі всіма значеннями списку
IndexOfKey              Повертає номер позиції заданого ключа у списку
IndexOfValue           Повертає номер позиції заданого значення у списку
RemoveAt                  Вилучає елемент на заданій позиції у списку
SetByIndex_______ Заміняє значення на заданій позиції у списку____
Доступ до елементів черги здійснюється за принципом „першим увійшов - першим вийшов" (FIFO - firs in, first out).
Черга реалізована в класі Queue. Клас містить такі конструктори:
Queue ([capacity [, growFactor]]); Queue (collection);
За замовчуванням місткість черги capacity дорівнює 32, а фактор збільшення growFactor - 2.0. Фактор збільшення задає множник, на який потрібно помножити місткість, якщо існуючої недостатньо. Друга версія конструктора використовує для утворення черги колекцію - екземпляр класу з підтримкою інтерфейсу ICollection.
Елементи черги можуть мати довільний тип.
Властивість Count повертає кількість елементів у черзі.
Із методів класу Queue зазначимо такі:
Метод
Зміст
Clear
Вилучає всі елементи з черги
Contains
Визначає, чи містить черга заданий елемент
CopyTo
Копіює елементи черги в одновимірний масив



Dequeue
Повертає значення першого елемента черги та вилучає його з

черги
Enqueue
Додає елемент наприкінці черги
Peek
Повертає значення першого елемента черги, однак не вилучає

його з черги
ToArray
Копіює елементи черги в масив

Доступ до елементів стека здійснюється за принципом „останнім увійшов - першим вийшов" (LIFO - last in, first out).
Стек реалізований у класі Stack. Клас налічує такі конструктори:
Stack ([capacity]);
Stack (collection);
За замовчуванням місткість стеку capacity дорівнює 10. Друга версія конструктора для утворення стека використовує колекцію.
Елементи стека можуть мати довільний тип.
Властивість Count повертає кількість елементів у стеку.
Із методів класу Stack зазначимо такі:
Метод
Зміст
Clear
Вилучає всі елементи зі стека
Contains
Визначає, чи містить стек заданий елемент
CopyTo
Копіює елементи стека в одновимірний масив
Peek
Повертає елемент на вершині стека, проте не вилучає його зі стека
Pop
Повертає елемент на вершині стека та вилучає його зі стека
Push
Додає елемент на вершину стека
ToArray
Копіює елементи стека в масив

Простір імен System.IO містить понад 50 класів, інтерфейсів і переліків, які дають змогу працювати з файлами та каталогами (папками). Додатково простір імен System.Windows.Forms містить декілька діалогових форм вибору файлів.
При роботі з файлами доцільно детально ознайомитися з функціональними можливостями елементів System.IO, оскільки Microsoft передбачив дуже широкий набір інструментів маніпулювання файловою системою. Ми ж розглянемо лише декілька з них.
Для поодиноких операцій над файлами використовують клас File. Він містить лише статичні методи, отож утворювати екземпляр класу нема необхідності.
Серед загальнодоступних методів класу File зазначимо
такі:
Метод
Зміст
AppendText
Додає текст в існуючий файл
Copy
Копіює файл
Create
Утворює файл
CreateText
Утворює файл і відкриває його для запису тексту
Delete
Вилучає файл
Exists
Перевіряє, чи існує файл
GetAttributes
Повертає атрибути файла
Move
Переміщає файл
Open
Відкриває файл
OpenRead
Відкриває файл для читання
OpenText
Відкриває файл для читання тексту
OpenWrite
Відкриває файл для запису
SetAttributes
Встановлює атрибути файла

Клас File містить також кілька методів для повернення або встановлення дати утворення файла, останнього доступу, останнього запису.
Наведемо простий приклад використання класу File:
if (openDlg.ShowDialog()==DialogResult.OK){ string s = openDlg.FileName; FileAttributes fa = File.GetAttributes(s); if ((fa & FileAttributes.Readonly) == FileAttributes.Readonly) MessageBox.Show("+a^ " + s + " є лише для читання";
}
Цей код активізує діалогову форму вибору файла та записує у змінну fa атрибути файла, які є набором бітових прапорців.
Якщо цей набір у позиції ознаки ReadOnly містить ненульовий біт, то виводиться повідомлення.
Якщо потрібно виконати декілька операцій над файлом, то значно ефективнішим буде використання класу FileInfo. Для роботи з файлом з допомогою цього класу потрібно утворити об'єкт. Єдиний конструктор класу має просту сигнатуру: public FileInfo(string fileName) ;
Клас FileInfo має такі загальнодоступні властивості:
Властивість
Зміст
Attributes
Атрибути файла
CreationTime
Час утворення файла
Directory
Каталог (тип DirectoryInfo), у якому розташований

файл
DirectoryName
Назва каталогу, у якому розташований файл
Exists
Повертає true, якщо файл існує
Extension
Розширення файла
FullName
Повний шлях до файла та назва файла
LastAccessTime
Час останнього доступу до файла
LastWriteTime
Час останньої модифікації файла
Length
Розмір файла
Name
Назва файла
Серед загальнодоступних методів класу FileInfo
зазначимо такі:

Метод
Зміст
AppendText
Додає текст у файл
CopyTo
Копіює файл
Create
Утворює файл
CreateText
Утворює текстовий файл
Delete
Вилучає файл
MoveTo
Переміщує файл
Open
Відкриває файл
OpenText
Відкриває файл для читання тексту
OpenWrite
Відкриває файл для запису

Аналогічно до файлів, для роботи з каталогами бібліотека .NET містить клас Directory зі статичними методами та клас
DirectoryInfo, екземпляр якого використовують за необхідності здійснення декількох операцій з каталогом. Серед методів класу Directory зазначимо такі:
Метод
Зміст
CreateDirectory
Утворює новий каталог
Delete
Знищує каталог
Exists
Визначає, чи існує каталог
GetCurrentDirectory
Повертає поточний каталог
GetDirectories
Повертає імена всіх підкаталогів у каталозі
GetFiles
Повертає імена всіх файлів у каталозі
GetFileSystemEntries
Повертає імена всіх файлів і підкаталогів
GetLogicalDrivers
Повертає список логічних дисків
GetParent
Повертає назву батьківського каталогу
Move
Переміщує каталог
SetCurrentDirectory
Встановлює поточний каталог

Клас Directory містить також декілька методів для повернення або встановлення дати утворення файла, останнього доступу, останнього запису.
Властивості класу DirectoryInfo подібні до властивостей класу FileInfo. З додаткових властивостей Зазначимо Root (повертає кореневу частину шляху) та Parent (повертає об'єкт, який є батьківським каталогом).
Методи класу DirectoryInfo подібні до методів класу Directory.
Бібліотека .NET дає змогу програмі вести моніторинг змін у файловій системі. Ця можливість реалізована в класі
FileSystemWatcher, який відстежує такі події:
Подія
Зміст
Changed
Модифікація файла або каталогу
Created
Утворення файла або каталогу
Deleted
Вилучення файла або каталогу
Error
Переповнення внутрішнього буфера
Renamed
Перейменування файла або каталогу

Щоб опрацювати одну із цих подій, необхідно утворити відповідну функцію та долучити її до списку обробників події.
Наприклад, для опрацювання події внесення змін у файли можна написати:
public static void OnChanged(
object sender, FileSystemEventArgs e){ MessageBox.Show(e.FullPath+": " + e.ChangeType) ;
}
Сигнатура методу повинна відповідати сигнатурі делегата FileSystemEventHandler. Клас FileSystemEventArgs має три властивості, які характеризують подію: Name або FullPath містять назву чи повний шлях зміненого файла (каталогу), а ChangeType - ознаку змін.
Наведемо тепер фрагмент коду, який демонструє використання класу FileSyst emWa tcher:
FileSystemWatcher fsw = new
FileSystemWatcher("C:\\"); fsw.Filter = "*.txt"; fsw.Changed += new
FileSystemEventHandler(OnChanged) ; fsw.NotifyFilter =
NotifyFilters.LastAccess|NotifyFilters.LastWrite; fsw.EnableRaisingEvents = true;
Код утворює об'єкт класу FileSystemWatcher і дає вказівку цьому об'єкту відстежувати зміни на диску C: у файлах із розширенням .txt. Потім додає обробник подій, який клас FileSystemWatcher активізує при отриманні повідомлення від операційної системи про внесення змін у txt-файли, зазначає, які події відстежувати, та вмикає моніторинг.
Перелічимо властивості класу FileSyst emWa tcher:
Властивість
Зміст
EnableRaisingEvents
Увімкнення/вимкнення моніторингу
Filter
Фільтр файлів для відстеження
IncludeSubdirectories
Ознака моніторингу дочірніх підкаталогів
InternalBufferSize
Розмір внутрішнього системного буфера
NotifyFilter
Список подій для моніторингу
Path
Шлях, по якому відстежують зміни
SynchronizingObject
Керування потоком виконання, який відстежує

зміни


Властивість NotifyFilter - це набір прапорців з перерахунку NotifyFilters:
Ознака
Значення
Моніторинг змін
Attributes
4
Атрибутів файлів
CreationTime
64
Часу створення файлів і каталогів
DirectoryName
2
Імен каталогів
FileName
1
Імен файлів
LastAccess
32
Часу останнього доступу
LastWrite
16
Часу останнього запису
Security
256
Атрибутів безпеки
Size
8
Розміру

Обмін інформацією передбачає наявність двох суб'єктів, які є джерелом та адресатом цієї інформації. Одним із суб' єктів обміну інформацією є програма. Якщо інформація передається від програми, то кажуть, що інформація виводиться. І навпаки, якщо програма отримує інформацію, то маємо справу з введенням інформації.
Суб'єкт обміну інформацією, який може її зберігати, називають сховищем даних. Це може бути файл, оперативна пам'ять, мережеве з'єднання, URL та інше.
Механізм, який реалізує процес обміну інформацією, називають потоком введення/виведення. При утворенні потоку йому вказують сховище даних, з яким він працюватиме.
Бібліотека .NET чітко розділяє сховища даних і потоки. Власне тому розглянуті у попередньому розділі класи роботи з файлами дають змогу широко маніпулювати файлами загалом, однак майже зовсім не містять функцій зчитування та запису даних.
Клас Stream
Усі потоки .NET є екземплярами класів, похідних від базового абстрактного класу Stream. Цей клас має п'ять загальнодоступних властивостей:
Властивість
Зміст
CanRead
Повертає ознаку доступу до читання даних
CanSeek
Повертає ознаку коректності переходу на задану позицію в потоці
CanWrite
Повертає ознаку доступу для запису даних
Length
Повертає довжину потоку в байтах
Position
Повертає поточну позицію у потоці

Властивості CanRead, CanSeek і CanWrite повертають значення true або false. Доступ до читання або запису визначається при утворенні потоку. Всі властивості (окрім Posit ion) мають доступ лише для читання.
Клас Stream містить одне статичне поле: Null. Це поле повертає потік, з яким не пов' язане сховище даних. При читанні з потоку Stream.Null ніякі дані не повертаються, а при записі в потік - не зберігаються.
Перелічимо загальнодоступні методи класу Stream:
Метод
Зміст
BeginRead
Починає асинхронну операцію зчитування
BeginWrite
Починає асинхронну операцію записування
Close
Закриває потік і звільняє зайняті ним ресурси
EndRead
Очікує завершення асинхронної операції зчитування
EndWrite
Очікує завершення асинхронної операції записування
Flush
Записує всі дані з внутрішнього буфера у сховище даних
Read
Зчитує послідовність даних
ReadByte
Зчитує один байт
Seek
Установлює позицію в потоці
SetLength
Установлює довжину потоку
Write
Записує послідовність байт
WriteByte
Записує один байт

Клас FileStream
Потоковий клас FileStream призначений для читання та запису як текстових, так і двійкових даних у довільний файл. Зазначимо, що існують спеціалізовані класи для деяких типів файлів, які є дещо ефективнішими порівняно з FileStream. Зокрема, нижче ми розглянемо класи роботи з текстовими файлами.
Клас FileStream має дев'ять конструкторів. Чотири з них використовують дескриптор файла Windows у стилі старого API.
Ми їх не розглядатимемо. Решта конструкторів опишемо наступною схемою:
public FileStream( string path, FileMode mode [,FileAccess access [,FileShare share [,int bufferSize [,bool useAsync ]]]]);
Параметр path задає повне ім'я файла.
Параметр mode визначає режим файла і може набувати одне із значень переліку FileMode: Append (додати), Create (утворити), CreateNew (утворити новий), Open (відкрити), OpenOrCreate (відкрити або утворити), Truncate (обрізати). Зауважимо, що некоректне значення mode може породжувати виняток (наприклад, Open для неіснуючого файла).
Параметр access доступу до файла може набувати одне зі значень переліку FileAccess: Read (читання), ReadWrite (читання та запис), Write (запис). Очевидно, що при утворенні потоку з атрибутом FileAccess.Read запис у файл буде недоступним.
Параметр share визначає доступ до файла з інших потоків. Він може набувати одне зі значень переліку FileShare: None (нема), Read (читання), ReadWrite (читання та запис), Write (запис). Якщо потік успішно утворений, то інші потоки можуть працювати з цим файлом відповідно до значення параметра share зазначеного потоку.
Параметр bufferSize задає бажаний розмір у байтах внутрішнього буфера читання. Параметр useAsync визначає, чи буде файл відкрито асинхронно.
Наведемо приклади утворення файлових потоків:
FileStream fs1 = new FileStream(
@"C:\Temp\File1.cs", FileMode.Create);
FileStream fs2 = new
FileStream(@"C:\Temp\File2 .cs",
FileMode.Create, FileAccess.Write);
FileStream fs3 = new
FileStream(@"C:\Temp\File3.cs
FileMode.Create, FileAccess.Read, FileShare.None, 2048, true);
Перший конструктор утворює потік і файл File1.cs з доступом „читання-запис" та надає іншим потокам доступ на читання. Другий конструктор утворює файл File2.cs з доступом лише для запису та надає іншим потокам доступ на читання. Третій конструктор утворює файл File3.cs для асинхронного доступу лише для читання, без права доступу іншим потокам, а також установлює розмір буфера.
Клас FileStream, окрім успадкованих від Stream, має такі властивості:
Властивість
Зміст
Handle
Дескриптор операційної системи для відкритого файла
IsAsync
Повертає ознаку асинхронності доступу
Name
Повертає ім'я об'єкта FileStream

Клас FileStream має два додаткових методи: Lock та Unlock. Метод Lock забороняє доступ до файла іншим потокам, а Unlock скасовує цю заборону.
За синхронних операцій введення-виведення робота програми зупиняється до завершення цих операцій. Якщо програма працює з великими файлами або з мережевими потоками, то складається враження, що вона „зависла".
За асинхронного введення-виведення виділяється окремий потік виконання. Це дає змогу програмі працювати, не очікуючи завершення операції введення-виведення. Зазначимо, що асинхронні методи не можна активізувати у випадку, якщо код, наступний за операцією введення-виведення, використовує результат цієї операції.
Щоб надати можливість повідомити програму про завершення асинхронної операції, список параметрів асинхронних методів містить параметр типу AsyncCallback. Цей параметр дає змогу означити функцію зворотного виклику, що передається як делегат. Коли асинхронна операція завершилася, то викликається функція зворотного виклику, в якій можна працювати з результатами операції.
Делегат AsyncCallback означений так:
public delegate void
AsyncCallback(IAsyncResult ar);
Оголосимо потокову змінну та функцію зворотного виклику:
public FileStream fs;
public void OnReadFinished(IAsyncResult asyncResult) {
int ReadCount = fs.EndRead(asyncResult); MessageBox.Show("Прочитано "+ReadCount+" байт.");
}
Наведемо тепер приклад використання асинхронних методів:
//пам'ять для читання
byte[] buffer = new byte[100 00 0];
//відкриття файла
fs = new FileStream(@"c:\temp\file1.cs",
FileMode.Open, FileAccess.Read, FileShare.None, 2048, true); //присвоєння делегату функції зворотного виклику AsyncCallback acb = new
AsyncCallback(OnReadFinished); //асинхронне читання
fs.BeginRead(buffer, 0, 100000, acb, null); // наступний код, який виконуватиметься без // очікування на завершення операції читання
Як тільки операцію асинхронного введення буде завершено, активізується метод OnReadFinished.
Зауважимо: якщо файл відкритий для синхронного доступу, то асинхронні методи працюватимуть також синхронно.
Клас MemoryStream
Клас MemoryStream призначений для обміну даними між програмою та областю пам'яті, яка є в цьому випадку сховищем даних.
Клас має декілька конструкторів. Найінформативніший з них такий:
public MemoryStream(
[byte[] buffer [, int index[, int count [, bool writable[, bool publiclyVisible]]]]]);
З цього синтаксису бачимо, що конструктор може не мати аргументів або мати лише декілька з них.
Параметр buffer задає масив байтів, який слугуватиме сховищем даних. Якщо аргумент відсутній, то утворюється динамічний буфер з нульовим розміром.
Параметр index зазначає індекс у масиві buffer, з якого починається сховище даних. За замовчуванням параметр дорівнює нулю.
Параметр count зазначає кількість байт в масиві buffer, виділених для сховища даних.
Параметр writable задає значення властивості CanWrite.
Параметр publiclyVisible визначає, чи можна отримати масив (тобто сховище даних) з допомогою методу GetBuffer.
Наступний код демонструє використання класу MemoryStream для копіювання файла в пам'ять:
FileStream fs =
File.OpenRead(@"c:\temp\file .cs") ;
MemoryStream ms = new MemoryStream();
ms .SetLength(fs.Length);
fs.Read(ms.GetBuffer(), 0, (int)fs.Length);
ms.Flush();
fs.Close();
Клас MemoryStream, окрім успадкованих від Stream, має додаткову властивість Capacity. Ця властивість повертає або встановлює кількість байт, виділених для потоку.
Клас MemoryStream має також два додаткових методи: GetBuffer повертає (якщо дозволено) внутрішній буфер, а WriteTo записує дані потоку в інший потік.
Клас NetworkStream
Клас NetworkStream отримує та відсилає через мережу байти процесу, який працює на другому кінці мережевого з'єднання. Цей клас розташований у просторі імен System.Net.Sockets.
Для утворення потоку необхідно задати мережеве з' єднання на основі сокета. Сокет - це об'єкт класу Socket або успадкованих від Socket класів: TcpListener, TcpClient та інших.
Для означення сокета потрібно задати адресу хоста (host). Ця адреса може бути числовою адресою TCP/IP або іменем хоста, яке операційна система може перетворити в числову адресу. Список таких імен хостів можна отримати з допомогою статичних методів класу Dns, розташованого у просторі імен System.Net. Ім'я хоста localhost представляє комп'ютер, на якому запущено програму.
Другим елементом, який означує сокет, є номер порту (port). Порти з номерами від 0 до 49151 вже призначені конкретним службам. Отож у власних програмах доцільно використовувати порти з номерами від 49152 до 65536.
Узагальнений конструктор класу NetworkStream має вигляд:
public NetworkStream( Socket socket,
[, FileAccess access[, bool ownsSocket]]);
Параметр socket задає сокет і є обов'язковим.
Параметр access визначає доступ до сокета і може набувати одне зі значень переліку FileAccess.
Параметр ownsSocket визначає, чи потік буде власником сокета. Якщо так, то сокет буде знищуватися при завершенні роботи потоку.
Деякі класи сокетів (наприклад, TcpClient) містять вбудовані мережеві потоки, які можна отримати методом
GetStream.
Клас NetworkStream, окрім успадкованих від Stream, має додаткову властивість Capacity, яка повертає або встановлює кількість байт, виділених для потоку.
Клас NetworkStream має також два додаткових методи: GetBuffer повертає внутрішній буфер, а WriteTo записує дані потоку в інший потік.
Наступний код демонструє процес введення даних з деякого мережевого сервера, тобто програма діє як клієнт:
byte[] buffer = new byte[2048];
TcpClient socket = new
TcpClient("localhost", 65535);
NetworkStream ns = socket.GetStream();
int count = ns.Read(buffer, 0, 2048);
ns.Close();
socket.Close ();
У цьому прикладі ми не утворювали екземпляр потоку, а використали для читання даних уже існуючий потік сокета. Метод Read робить спробу прочитати й розмістити в buffer перших 2048 байт, викладених в порті з номером 65535 комп'ютера, заданого хостом. Якщо на цьому комп'ютері відсутня програма (сервер), яка викладає дані на порт 65535, то виконання наведеного коду завершиться винятком SocketException.
Наступний код демонструє процес викладання даних на деякий порт, тобто програма діє як сервер:
string msg="3B'fl30K із сервером встановлений";
TcpListener tcpl = new TcpListener(65535);
tcpl.Start() ;
Socket sckt = tcpl.AcceptSocket();
if (sckt.Connected) { NetworkStream ns= new NetworkStream(sckt); byte[] bytes= Encoding.ASCII.GetBytes(msg); ns.Write(bytes, 0, bytes.Length); ns.Flush(); ns.Close(); sckt.Close();
}
Метод tcpl. Start дає команду почати прослуховування порту в очікуванні нового з' єднання по мережі. Метод AcceptSocket очікує реального підключення клієнта. Коли підключення відбулося, метод повертає об'єкт sckt класу Socket, який використовують для пересилання даних.
З метою підвищення ефективності коду в .NET реалізовано успадкований від Stream клас BufferedStream, який додає рівень буферизації до іншого потоку для операцій читання та запису. Цей клас не може бути успадкованим. При використанні класу BufferedStream операційна система надає дані блоками, які забезпечують найкращу продуктивність. Окрім того, клас може зберігати в пам'яті результати декількох операцій запису, і записати їх у сховище даних лише тоді, коли цей запис буде найефективнішим.
Простір імен System.Security.Cryptography має ще один успадкований від Stream клас - CryptoStream. Цей клас є потоковою реалізацією криптографії. Його можна додати до існуючого потоку з метою шифрування інформації.
Розглянуті вище потокові класи є зручними для переміщення даних як послідовності байтів. Однак вони недостатньо ефективні для операцій над даними. Наприклад, щоб отримати з файла ціле число типу int, необхідно прочитати 4 байти в масив байтів, який після цього потрібно інтерпретувати як ціле.
Щоб забезпечити більш структурований доступ до даних із потоків, у просторі System.IO розташовано кілька класів для зчитування та запису даних.
Клас BinaryWriter призначений для запису значення типізованої змінної в потік. Конструктор класу має такий синтаксис:
BinaryWriter([Streamoutput,[Encoding encoding]]);
Параметр output зазначає потік, з яким працюватиме клас. Параметр encoding дає змогу під час виводу символьних даних в потік конвертувати їх в інші кодові формати.
Наступний код демонструє використання класу
BinaryWriter:
FileStream fs=File.Create (@"c: \temp\file.dat") ;
BinaryWriter bw = new BinaryWriter(fs);
bw.Write((float) 3.14);
int i = 10;
bw.Write (i);
string s = "стрічка";
bw.Write (s);
bw.Flush();
bw.Close();
Клас BinaryWriter має єдину властивість BaseStream, яка повертає потік, в який пише об' єкт класу.
Перелічимо загальнодоступні методи класу BinaryWriter:
Метод
Зміст
Close
Закриває об'єкт класу та відповідний йому потік
Flush
Записує всі дані з буфера у сховище даних потоку
Seek
Установлює позицію в потоці
Write
Записує типізоване значення в потік

Зазначимо, що метод Write сильно перевантажений, оскільки підтримує запис більшості основних типів даних.
Клас BinaryReader призначений для читання даних з потоку в типізовані змінні. Конструктор класу має такий синтаксис:
BinaryReader(Stream input, [Encoding encoding]);
Параметр input визначає потік, з яким працюватиме клас. Необов'язковий параметр encoding дає змогу у процесі читання символьних даних з потоку конвертувати їх в інші кодові формати.
Наступний код демонструє використання класу BinaryReader:
FileStream fs =
File.OpenRead(@"c:\temp\file.dat");
BinaryReader br = new BinaryReader(fs);
float f = br.ReadSingle();
int i = br.ReadInt32();
string s = br.ReadString();
br.Close();
Клас BinaryReader має єдину властивість BaseStream, яка повертає потік, з якого читає об' єкт класу.
Призначення наступних методів класу очевидне з назви: Close, ReadBoolean, ReadByte, ReadBytes, ReadChar, ReadChars, ReadDecimal, ReadDouble, ReadInt16, ReadInt32, ReadInt64, ReadSByte, ReadSingle, ReadString, ReadUInt16, ReadUInt32, ReadUInt64. Окрім перелічених клас має ще два методи: PeekChar повертає наступний символ, не змінюючи позиції в потоці, а Read повертає символі змінює позицію.
Класи FileStream, BinaryReader та BinaryWriter використовують для читання та запису текстових файлів. Однак, з метою підвищення ефективності та зручності програмування, доцільно використовувати для роботи з текстом спеціальні класи, які є нащадками абстрактних класів TextReader та TextWriter. Методи цих класів вміють читати та записувати стрічку, тобто набір символів, який завершується комбінацією „по­вернення каретки - переведення стрічки" ((char) 13 (char) 10). Окрім цього, класи автоматично розпізнають і підтримують задане у файлі кодування символів (ASCII, Unicode, UTF7, UTF8).
Наведемо деякі загальнодоступні методи класу TextReader:
Метод
Зміст
Close
Закриває об' єкт і звільняє зайняті ним ресурси
Peek
Повертає наступний символ без зміни позиції
Read
Читає символи з відповідного об' єктові потоку
ReadBlock
Читає буфер з відповідного об' єктові потоку
ReadLine
Читає стрічку символів з відповідного об' єктові потоку
ReadToEnd
Читає символи від поточної позиції до кінця потоку
Клас TextWriter має такі методи:
Метод
Зміст
Close
Закриває об' єкт і звільняє зайняті ним ресурси
Flush
Записує всі дані з буфера у сховище даних
Write
Записує символи у відповідний об' єктові потік
WriteLine
Записує стрічку у відповідний об' єктові потік
Клас TextWriter має також властивості:
Властивість
Зміст
Encoding
Повертає поточне кодування тексту
FormatProvider Повертає об'єкт із урахуванням культурозалежних

аспектів форматування
NewLine
Повертає або встановлює послідовність символів, які

означають кінець стрічки тексту

Реалізацією класів TextReader та TextWriter для роботи з потоками є класи StreamReader та StreamWriter.
Узагальнена схема конструктора класу StreamReader має такий вигляд:
public StreamReader(
Stream stream | string path [, Encoding encoding
[, bool detectEncodingFromByteOrderMarks [, int bufferSize]] ]);
Зазначимо, що схема не охоплює синтаксис усіх конструкторів класу. Режим і тип доступу не використовують, оскільки клас призначений лише для читання.
Клас StreamReader може читати дані з файла (параметр path) або з іншого потоку (параметр stream).
Параметр encoding задає метод кодування.
Параметр detectEncodingFromByteOrderMarks
зазначає, чи шукати ознаку кодування символів у файлі (потоці).
Параметр bufferSize задає мінімальний розмір буфера для читання.
Екземпляр класу StreamReader можна також отримати з інших класів. Наприклад, екземпляр цього класу повертають методи OpenText і CreateText класу FileInfo.
Клас StreamWriter працює практично так само, як і StreamReader, тільки використовується для запису у файл або інший потік. Конструктори класу StreamWriter використовують ті ж параметри, що й конструктори класу StreamReader.
Наступний код демонструє використання класів StreamReader і StreamWriter:
FileStream fs = File.Create(@"e:\File.txt");
//Запис у файл
StreamWriter sw = new StreamWriter(fs);
sw . WriteLine ( "Записано класом StreamWriter.");
sw.Flush();
sw.Close();
//Читання з файла
StreamReader sr = new
StreamReader(@"e:\File.txt") ;
MessageBox.Show(sr.ReadLine());
sr.Close();
Класи StringReader і StringWriter також є дочірніми для класів TextReader і TextWriter. Сховищем даних для цих класів є стрічка. Класи StringReader і StringWriter мають такі ж методи та властивості, як і класи StreamReader - StreamWriter. Додатково клас StreamWriter має метод GetStringBuilder, який повертає об'єкт класу StringBuilder.
Модифікуємо попередній код під використання класів StringReader і StringWriter:
StringBuilder sb = new StringBuilder();
//Запис у стрічку
StreamWriter sw = new StreamWriter(sb); sw.WriteLine ("Записано класом StreamWriter."); sw.Close (); //Читання зі стрічки StreamReader sr = new
StreamReader(sb.ToString()); MessageBox.Show(sr.ReadToEnd()); sr.Close();
Серіалізація - це процес перетворення даних об'єкта у формат, який можна зберігати або транспортувати. Серіалізація дає змогу записати об'єкт у сховище даних з допомогою потоку. Зворотний процес - відновлення об'єкта з допомогою потоку зі сховища даних - називають десеріалізацією.
Серіалізувати можна лише об'єкти класів, які перед своїм оголошенням містять атрибут [Serializable]. .NET надає дві технології серіалізації.
Бінарна (двійкова) серіалізація передбачає збереження точної копії об'єкта. Це може бути корисним для відтворення об'єкта в різних сеансах роботи програми, для передавання між різними програмами та мережею. З метою відтворення бінарно серіалізованого об'єкта програма повинна знати його тип. У випадку бінарної серіалізації об'єкт-десеріалізатор залежний від версії модуля, у якому серіалізовано стан відповідного об'єкта.
Наступна схема демонструє процес бінарної серіалізації- десеріалізації.
//клас Sample будемо серіалізувати [Serializable] public class Sample { public string Title;
}
//фрагмент коду серіалізації Sample obj = new Sample(); obj.Title = "Об'єкт класу Sample"; FileStream writer = new FileStream ("c:\\Sample.dat", FileMode.Create);
BinaryFormatter bf = new BinaryFormatter(); //бінарна серіалізація bf.Serialize(writer, obj); writer.Close();
//фрагмент коду десеріалізації FileStream reader = new
FileStream("c:\\Sample.dat", FileMode.Open); Sample newobj =
(Sample)bf.Deserialize(reader);
Клас BinaryFormatter оголошений у просторі імен System.Runtime.Serialization.Formatters.Binary.
XML-серіалізація дає змогу зберегти лише загальнодоступні властивості та поля. Здебільшого цього достатньо для смислового відтворення об'єкта. Оскільки XML - відкритий стандарт, XML- серіалізація є хорошим засобом спільного використання даних у мережі. У випадку XML-серіалізації проблема версійності складеного модуля, яким виконано серіалізацію стану об' єкта, не виникає. Проте необхідно зважати на суттєве зростання пакетів серіалізованої інформації (до об'єму даних додається суттєвий об'єм XML-розмітки).
XML-серіалізація може бути виконана, наприклад, наступним кодом:
XmlSerializer ser = new
XmlSerializer(typeof(Sample)); TextWriter writer = new
StreamWriter("c:\\Sample.xml"); ser.Serialize(writer, obj); writer.Close();
Клас XmlSerializer оголошений у просторі імен System. Xml.Serialization.
Різновидом-XML серіалізації є SOAP серіалізація, яка використовує відкритий стандарт SOAP. Для її реалізації можна використати спеціалізований клас SoapFormatter, оголошений у просторі    імен                         System.Runtime.Serialization.
Formatters.Soap.

Немає коментарів:

Дописати коментар