Студопедия

КАТЕГОРИИ:


Архитектура-(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

 

Елемент Опис
Close Закрити файл і звільнити пов'язані з ним ресурси. Якщо в процесі запису використовується буфер, він буде автоматично очищений
Flush Очистити всі буфери для поточного файлу і записати накопичені в них дані в місце їх постійного зберігання. Сам файл при цьому не закривається
NewLine     Використовується для завдання послідовності символів, що означають початок нового рядка. За умовчанням використовується послідовність “повернення каретки” - “переведення рядка” (\r \n)
Write Записати фрагмент тексту в потік
WriteLine Записати рядок в потік і перейти на інший рядок

 

Таблиця 11.7

Найбільш важливі елементи класу TextReader

 

Елемент Опис
Peek Повернути наступний символ, не змінюючи позицію покажчика у файлі
Read Рахувати дані з вхідного потоку
ReadBlock Рахувати з вхідного потоку вказану користувачем кількість символів і записати їх в буфер, починаючи із заданої позиції
ReadLine Рахувати рядок з поточного потоку і повернути його як значення типу string. Порожній рядок (null) означає кінець файлу (EOF)
ReadToEnd Рахувати всі символи до кінця потоку, починаючи з поточної позиції, і повернути дані як один рядок типу string

 

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

У лістингу 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

 

Елемент Опис
BaseStream Базовий потік, з яким працює об'єкт ВinaryWriter
Close Закрити потік
Flush Очистити буфер
Seek Встановити позицію в потоці
Write Записати значення в потік

 

Таблиця 11.9

Найбільш важливі елементи класу BinaryReader

 

Елемент Опис
BaseStream Базовий потік, з яким працює об'єкт BinaryReader
Close Закрити потік
PeekChar Повернути наступний символ без переміщення внутрішнього покажчика в потоці
Read Рахувати потік байтів або символів і зберегти в масиві
ReadXXXX Рахувати з потоку дані певного типу (наприклад, Readboolean, Readbyte, ReadInt32 і т. д.)

 

У лістингу 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; Просмотров: 519; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.125 сек.