КАТЕГОРИИ: Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748) |
Асинхронне уведення-виведення
Клас Stream (і, відповідно, FileStream) підтримує два способи виконання операцій уведення-виведення: синхронний і асинхронний. За умовчанням файли відкриваються в синхронному режимі, тобто подальші оператори виконуються тільки після завершення операцій введення-виведення. Для тривалих файлових операцій ефективніше виконувати уведення-виведення асинхронно, в окремому потоці виконання. При цьому в первинному потоці можна виконувати інші операції. Для асинхронного уведення-виведення необхідно відкрити файл в асинхронному режимі, для цього використовується відповідний варіант перевантаженого конструктора. Асинхронна операція введення ініціюється за допомогою методу BeginRead. Окрім характеристик буфера, в який виконується введення, в цей метод передається делегат, який задає метод, що виконується після завершення введення. Цей метод може ініціювати обробку отриманої інформації, відновити операцію читання або виконати будь-які інші дії, наприклад, перевірити успішність введення і повідомити про його завершення. Зазвичай в цьому методі викликається метод EndRead, який завершує асинхронну операцію. Аналогічно виконується і асинхронне виведення. У лістингу 11.2 приведений приклад асинхронного читання з файлу великого об'єму і паралельного виконання діалогу з користувачем.
Лістинг 11.2. Асинхронне введення using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO;
namespace examp75 { class Demo { FileStream f; byte[] buf = new byte[66666666]; AsyncCallback callback;
public void UserInput() // діалог з користувачем { string s; do { Console.WriteLine("Введіть рядок. Enter для завершення "); s = Console.ReadLine(); } while (s.Length!= 0); }
public void OnCompletedRead(IAsyncResult ar) // 1 { int bytes = f.EndRead(ar); Console.WriteLine("Налічено " + bytes); } public void AsyncRead() { try { f = new FileStream("1.txt", FileMode.Open, FileAccess.Read, FileShare.Read, buf.Length, true); // 2 callback = new AsyncCallback(OnCompletedRead); //3 f.BeginRead(buf, 0, buf.Length, callback, null); // 4 } catch (Exception e) { Console.WriteLine("Error " + e.Message); } } } class Program { static void Main(string[] args) { Demo d = new Demo(); d.AsyncRead(); d.UserInput(); } } }
Для зручності сприйняття операції читання з файлу і діалогу з користувачем оформлені в окремий клас Demo. Метод OnCompletedRead (оператор 1) повинен отримувати один параметр стандартного типу IAsyncResult, що містить відомості про завершення операції, які передаються в метод EndRead. Файл відкривається в асинхронному режимі, про це говорить значення true останнього параметра конструктора (оператор 2). У операторові 3 створюється екземпляр стандартного делегата AsyncCallback, який ініціалізувався методом OnCompletedRead. За допомогою цього делегата метод OnCompletedRead передається в метод BeginRead (оператор 4), який створює окремий потік, починає асинхронне введення і повертає управління в потік, що викликає. Зворотний виклик методу OnCompletedRead відбувається при завершенні операції введення. При достатньо довгому файлі verybigfile можна переконатися, що запрошення до введення в методі UserInput видається раніше, ніж повідомлення про завершення операції введення з методу OnCompletedRead. Приклад, приведений в лістингу 11.2, максимально спрощений для демонстрації методів BeginRead і EndRead, тому в ньому немає необхідних перевірок наявності файлу, успішності читання і так далі.
11.3. Потоки символів Символьні потоки StreamWriter і StreamReader працюють з Unicode-символами. Ці потоки є спадкоємцями класів TextWriter і TextReader. У таблицях 11.6 і 11.7 приведені найбільш важливі елементи цих класів. Як бачите, довільний доступ для текстових файлів не підтримується.
Таблиця 11.6 Найбільш важливі елементи базового класу TextWriter
Таблиця 11.7 Найбільш важливі елементи класу TextReader
Ви вже знайомі з деякими методами, приведеними в цих таблицях: впродовж всього посібника постійно використовувалися методи читання з текстових потоків і запису в текстові потоки, але не для дискових файлів, а для консолі, яка є їх окремим випадком. У лістингу 11.3 створюється текстовий файл, в який записуються два рядки. Другий рядок формується з перетворених чисельних значень змінних і пояснюючого тексту. Вміст файлу можна подивитися в будь-якому текстовому редакторові. Файл створюється в тому ж каталозі, куди середовище записує виконуваний файл. За умовчанням це каталог...\ConsoleApplication1\bin\Debug.
Лістинг 11.3. Виведення в текстовий файл
using System; using System.IO; using System.Collections.Generic; using System.Linq; using System.Text;
namespace examp76 { class Program { static void Main(string[] args) { try { StreamWriter f = new StreamWriter("text.txt"); f.WriteLine("ABCDEF:"); double a = 12.234; int b = 29; f.WriteLine(" a = {0,6:C} b = {1,2:X}", a, b); Console.WriteLine(" a = {0,6:C} b = {1,2:X}", a, b); f.Close(); } catch(Exception e) { Console.WriteLine("Error: " + e.Message); return; } } } }
У лістингу 11.4 файл, створений в попередньому прикладі, виводиться на екран.
Лістинг 11.4. Читання текстового файлу
using System; using System.IO; namespace exam77 { class Class1 { static void Main() { try { StreamReader f = new StreamReader("1.txt"); string s = f.ReadToEnd(); Console.WriteLine(s); f.Close(); } catch(FileNotFoundException e) { Console.WriteLine(e.Message); Console.WriteLine(" Проверьте правильность имени файла!"); return; } catch(Exception e) { Console.WriteLine("Error:" + e.Message); return; } } } }
У цій програмі весь файл прочитується за один прийом за допомогою методу ReadToEnd. Частіше виникає необхідність прочитувати файл порядково, такий приклад приведений в лістингу 11.5.
Лістинг 11.5. Порядкове читання текстового файлу using System; using System.IO; using System.Collections.Generic; using System.Linq; using System.Text;
namespace examp78 { class Class1 { static void Main() { try { StreamReader f = new StreamReader("1.txt"); string s; long i = 0; while ((s = f.ReadLine())!= null) Console.WriteLine(" {0}: {1} ", ++i, s); f.Close(); } catch(FileNotFoundException e) { Console.WriteLine(e.Message); Console.WriteLine(" Перевірте правильність імені файлу!"); return; } catch (Exception e) { Console.WriteLine("Error: " + e.Message); return; } } } }
Приклад перетворення чисел, що містяться в текстовому файлі, в їх внутрішню форму представлення приведений в лістингу 11.6. У програмі обчислюється сума чисел в кожному рядку. На вміст файлу накладаються строгі обмеження: числа мають бути розділені рівно одним пропуском, після останнього числа в рядку пропуску бути не повинно, файл не повинен закінчуватися символом переведення рядків. Методи розбиття рядка і перетворення в цілочисельне представлення розглядалися раніше.
Лістинг 11.6. Перетворення рядків в числа using System; using System.IO; namespace examp80 { class Class1 { static void Main() { try { StreamReader f = new StreamReader("1.txt"); string s; const int n = 20; int[] a = new int[n]; string[] buf; while ((s = f.ReadLine())!= null) { buf = s.Split(' '); long sum = 0; for (int i = 0; i < buf.Length; ++i) { a [i] = Convert.ToInt32(buf[i]); sum += a [i]; } Console.WriteLine("{0} сумма: {1}", s, sum); } f.Close(); } catch(FileNotFoundException e) { Console.WriteLine(e.Message); Console.WriteLine(" Перевірте правильність імені файлу!"); return; } catch (Exception e) { Console.WriteLine("Error; " + e.Message); return; } } } }
Результат роботи програми: 1 2 4 сума: 7 3 44 -3 6 сума: 50 8 1 1 сума: 10 11.4. Двійкові потоки
Двійкові файли зберігають дані в тому ж вигляді, в якому вони представлені в оперативній пам'яті, тобто у внутрішній формі представлення. Двійкові файли застосовуються не для перегляду їх людиною, а для використання в програмах. Вихідний потік BinaryWriter підтримує довільний доступ, тобто є можливість виконувати запис в довільну позицію двійкового файлу. Двійковий файл відкривається на основі базового потоку, який найчастіше використовує потік FileStream. Основні методи двійкових потоків приведені в таблицях 11.8 і 11.9.
Таблиця 11.8 Найбільш важливі елементи класу BinaryWriter
Таблиця 11.9 Найбільш важливі елементи класу BinaryReader
У лістингу 11.7 приведений приклад формування двійкового файлу. У файл записується послідовність дійсних чисел, а потім для демонстрації довільного доступу третє число замінюється числом 8888.
Лістинг 11.7. Формування двійкового файлу using System; using System.IO; namespace examp81 { class Class1 { static void Main() { try { BinaryWriter fout = new BinaryWriter( new FileStream(@"D:\1.txt", FileMode.Create)); double d = 0; while (d < 4) { fout.Write(d); d += 0.33; }; fout.Seek(16, SeekOrigin.Begin); // другий елемент файлу fout.Write(8888d); fout.Close(); } catch(Exception e) { Console.WriteLine("Error: " + e.Message); return; } } } } При створенні двійкового потоку в нього передається об'єкт базового потоку. При установці покажчика поточної позиції у файлі враховується довжина кожного значення типу doublе - 8 байт. У лістингу 11.8 приводиться програма, яка за допомогою екземпляра Binaryreader прочитує вміст файлу в масив дійсних чисел, а потім виводить цей масив на екран. При читанні береться до уваги, що метод ReadDoublе при виявленні кінця файлу генерує виключення EndOfStreamException. Оскільки в даному випадку це не помилка, тіло обробника виключень порожнє.
Лістинг 11.8. Читання двійкового файлу using System; using System.IO; namespace examp82 { class Class1 { static void Main() { try { FileStream f = new FileStream(@"D:\1.txt", FileMode.Open); BinaryReader fin = new BinaryReader(f); long n = f.Length / 8; // кількість чисел у файлі double[] х = new double[n]; long i = 0; try { while (true) х[i++] = fin.ReadDouble(); // читання } catch (EndOfStreamException e) {} foreach (double d in х) Console.Write(" " + d); // виведення fin.Close(); f.Close(); } catch (FileNotFoundException e) { Console.WriteLine(e.Message); Console.WriteLine(" Перевірте правильність імені файлу!"); return; } catch (Exception e) { Console.WriteLine("Error: " + e.Message); return; } } } } Результат роботи програми:
0 0,33 8888 0,99 1,32 1,65 1,98 2,31 2,64 2,97 3,3 3,63 3,96
Дата добавления: 2014-12-27; Просмотров: 562; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |