1629295403-b876e2087bddebea4bc9666fb2377a02 (846199), страница 85
Текст из файла (страница 85)
Щелкните правой кнопкой мыши на проекте ClassLibraryDriver и выберите в меню Set as Startup Project.Тем самым вы указываете С#, где находится функция Main () для данного решения. Она должна находиться в сборке драйвера, но не в сборке библиотеки классов.6. В файле Program, cs проекта ClassLibraryDriver добавьте в функциюMain () исходный текст наподобие приведенного:MyLibrary myLib = new M y L i b r a r y ( ) ;// Или что именно вы// хотите вызывать// вызов библиотечной функцииmyLib.LibraryFunctionl();// Вызов статической функцииint result = MyLibrary.LibraryFunction2();Другими словами, напишите программу, которая использует классы и методы избиблиотеки. Вы уже сталкивались с этим ранее как в данной главе, так и в другихглавах книги — например, когда вызывали метод WriteLine () класса Console из библиотеки .NET Framework.
(Console находится в пространстве именSystem в файле mscorlib . dll.)Код примера библиотеки и драйвера приведен выше — см. листинг демонстрационной программы ClassLibrary.7. Выберите команду меню P r o j e c t s Add Reference.8. В диалоговом окне Add Reference щелкните на вкладке Projects. Выберитеваш проект ClassLibrary и щелкните на кнопке ОК.Вы можете также добавить директиву using для пространства имен ClassLibrary в файл Program, cs проекта ClassLibraryDriver, чтобы сэкономить на набираемом тексте.В любой программе, которую вы напишете в будущем, достаточно включить директиву using для пространства имен вашей библиотеки классов и добавить ссылку на.DLL-файл, содержащий библиотеку, чтобы иметь возможность использовать библиотечные классы в своей программе. Именно так программы в данной книге применяютклассы из библиотеки .NET Framework.Глава 19.
Работа с файлами и библиотеками433Хранение данных в файлахКонсольные программы в настоящей книге в большинстве случаев получают входныеданные с консоли и выводят результат работы на консоль. Однако стоит заметить, чтовероятность встретить в реальном мире программу, не работающую с файлами, сопоставима с вероятностью встретить в академическом институте рекламу казино в Ницце.Классы для работы с файлами определены в пространстве имен System.IO. Базовым классом для файлового ввода-вывода является класс FileStream. Для работы с файломпрограммист должен его открыть.
Команда open подготавливает файлк работе и возвращает его дескриптор. Обычно дескриптор — это просто число, котороеиспользуется всякий раз при чтении из файла или записи в него.Асинхронный ввод-вывод: есть ли что-то хуже ожидания?Обычно программа ожидает завершения ее запроса на ввод-вывод и толькозатем продолжает выполнение. Вызовите метод read ( ) , и в общем случаевы не получите управление назад до тех пор, пока данные из файла не будут считаныТакой способ работы называется синхронным вводом-выводом.Классы С# System.IO поддерживают также и асинхронный ввод-вывод.
При использовании асинхронного ввода-вывода вызов read () тут же вернет управлениепрограмме, позволяя ей заниматься чем-то еще, пока ее запрос на чтение данных изфайла выполняется в фоновом режиме. Программа может проверить флаг выполнениязапроса, чтобы узнать, завершено ли его выполнение.Это чем-то напоминает варианты приготовления гамбургеров. При синхронном изготовлении вы нарезаете мясо и жарите его, после чего нарезаете лук и выполняете всеостальные действия по приготовлению гамбургера. При асинхронном приготовлениивы начинаете жарить мясо, и, поглядывая на него, тут же, не дожидаясь готовностимяса, начинаете резать лук и делать все остальное.Асинхронный ввод-вывод может существенно повысить производительность программы, но при этом вносит дополнительный уровень сложности.С# использует более интуитивный подход.
Он связывает каждый файл с объектомкласса FileStream. Конструктор класса FileStream открывает файл, а методыFileStream выполняют операции ввода-вывода.F i l e S t r e a m — не единственный класс, который может осуществлять файловыйввод-вывод. Однако он предоставляет хорошую основу для работы с файлами, выполняя90% всех ваших нужд по работе с ними. Это корневой класс, описываемый в данномразделе. Он достаточно хорош для С# и для вас.FileStream— фундаментальный класс. Весь набор его действий — это открытие файла, чтение и запись блока байтов. К счастью, пространство имен System.І0 содержит, помимо прочего, следующий набор классов, которые обернуты вокруг FileStream и предоставляют более простые и богатые возможности.BinaryReader/BinaryWriter — пара потоковых классов, которые содержатметоды для чтения и записи каждого из типов-значений: ReadChar (), Write-434Часть VII.
Дополнительные главыChar (), ReadByte (), WriteByte () и так далее. Эти классы полезны для чтения и записи объекта в бинарном (не читаемом человеком) формате, в противоположность текстовому формату. Для работы с бинарными данными можно использовать массив или коллекцию элементов типа Byte.TextReader/TextWriter— пара классов для чтения символов (текста).классыпредоставляютсявдвухвидах(наборахподклассов):ЭтиStrin-gReader/StringWriter и StreamReader/StreamWriter.StringReader/StringWriter— простые потоковые классы, которые ограничены чтением и записью строк.
Они позволяют рассматривать строку как файл,предоставляя альтернативу доступу к символам строк с помощью записи с использованием квадратных скобок ( [ ] ) , цикла foreach или методов классаString наподобие Split (), Concatenate () и IndexOf ( ) . Вы считываетеи записываете строки почти так же, как и файлы. Этот метод полезен для длинныхфайлов с сотнями или тысячами символов, которые вы хотите обработать вместе.Методы в этих классах аналогичны методам классов StreamReader и StreamWriter, описываемым далее.StreamReader/StreamWriter— более интеллектуальные классы чтенияи записи текста.
Например, класс StreamWriter имеет метод WriteLine (),очень похожий на метод класса Console. StreamReader имеет соответствующий метод ReadLine () и очень удобный метод ReadToEnd ( ) , собирающийвесь текстовый файл в одну группу и возвращающий считанные символы какстроку string (которую вы можете затем использовать с классом StringReader, циклом foreach и тому подобным).TextReader/TextWriter применяются как сами по себе, так и их более удобныеподклассы, такие как StreamReader/StreamWriter.В следующем разделе будут рассмотрены демонстрационные программы FileWrite и FileRead, которые иллюстрируют способы использования классов для текстового ввода-вывода.Использование Stream WriterПрограммы генерируют два вида вывода.Некоторые программы пишут блоки данных в виде байтов в чисто бинарном формате.
Этот тип вывода полезен для эффективного сохранения объектов (например, файл объектов Student, которые сохраняются междузапусками программы в файле на диске).Большинство программ читает и записывает информацию в виде текста,который может читать человек. Классы StreamWriter и StreamReader являются наиболее гибкими классами для работы с даннымив таком виде.Данные в удобном для чтения человеком виде ранее назывались ASCIIстроками, а сейчас — ANSI-строками. Эти два термина указывают названияорганизаций по стандартизации, которые определяют соответствующиестандарты. Однако кодировка ANSI работает только с латинским алфавитомГлава 19. Работа с файлами и библиотеками435и не имеет кириллических символов, символов иврита, арабского языка или хиныне говоря уж о такой экзотике, как корейские, японские или китайские иероглифыГораздо более гибким является стандарт Unicode, который включает ANSI-символкак свою начальную часть, а кроме них — массу других алфавитов, включая все перечисленные выше.
Unicode имеет несколько форматов, именуемых кодировкамиформатом по умолчанию для С# является UTF8.Приведенная далее демонстрационная программа FileWrite считываетстроки данных с консоли и записывает их в выбранный пользователем файл// FileWrite - запись ввода с консоли в текстовый файлusing System;using System.10; // Требуется для работы с файламиnamespace FileWrite{- public class Program{public static void Main(string []args)// Создание объекта для имени файла — цикл while// позволяет пользователю продолжать попытки до тех// пор, пока файл не будет успешно открытStreamWriter sw = null;string sFileName = "";while(true){try{// Ввод имени файла для вывода (просто Enter для// завершения программы)Console.Write("Введите имя файла "+ "(пустое имя для завершения):");sFileName = Console.ReadLine();if (sFileName.Length == 0){// Имени файла нет — выходим из циклаbreak;}// Открываем файл для записи; если файл уже// существует, генерируем исключение:// FileMode.CreateNew - для создания файла, если// он еще не существует и генерации исключения при// наличии такого файла; FileMode.Append для// создания нового файла или добавления данных к// существующему файлу; FileMode.Create для// создания нового файла или урезания уже// имеющегося до нулевого размера.
Возможные// варианты FileAccess: FileAccess.Read,// FileAccess.Write, FileAccess.ReadWriteFileStream fs = File.Open(sFileName,FileMode.CreateNew,FileAccess.Write);// Генерируем файловый поток с UTF8-символами (по436Часть VII. Дополнительные главы// умолчанию второй параметр дает UTF8, так что он// может быть опущен)sw = new StreamWriter(fs,System.Text.Encoding.UTF8);// Считываем по одной строке, выводя каждую из них// в FileStream для записиConsole.WriteLine("Введите текст " +"(пустую строку для в ы х о д а ) " ) ;while(true){// Считываем очередную строку с консоли; если// строка пуста, завершаем циклstring slnput = Console.ReadLine();if (slnput.Length == 0){break;}// Записываем считанную строку в файл выводаsw.WriteLine(slnput);}// Закрываем созданный файлsw.Close();sw = null; // Желательно обнуление ссылочных// переменных после использования}catch(IOException fe){// Произошла ошибка при работе с файлом — о ней// надо сообщить пользователю вместе с полным// именем файлаstring sDir = Directory.GetCurrentDirectory();string s = Path.Combine(sDir, sFileName);Console.WriteLine("Ошибка с файлом {О}", s ) ;// Теперь выводим сообщение об ошибке из// исключенияConsole.WriteLine(fe.Message);// Ожидаем подтверждения пользователяConsole.WriteLine("Нажмите <Enter> для " +"завершения программы...");Console.Read();Демонстрационная программа FileWrite использует пространства имен System.