Учебное пособие (1077022), страница 20
Текст из файла (страница 20)
Как и вязыке C++ в C# символ «\» внутри строки используется для созданияспециальных символов, например «\n» – перевод строки. В соответствии справилами языка C# имя каталога должно быть объявлено как «c:\\», приэтом символ «\» как и в C++ удваивается. Но особенностью языка C#является то, что если перед строковым значением стоит символ «@», тоспециальные символы игнорируются и удваивать символ «\» не требуется.Результаты вывода в консоль:Список файлов каталога c:\c:\AVScanner.inic:\pagefile.sysc:\SecurityScanner.dllСписок подкаталогов каталога c:\c:\$Recycle.Binc:\appsc:\Documents and Settingsc:\Program Filesc:\Program Files (x86)c:\Tempc:\Windows7.2 Чтение и запись текстовых файловВ данном разделе рассмотрен наиболее простой способ работы стекстовыми файлами на основе класса File.Класс File обладает достаточно широкой функциональностью.
С егопомощью возможно копирование (метод Copy), перемещение (методMove), удаление (метод Delete) файлов в файловой системе.163У класса файл существует достаточно большое количество методовдля работы с файлами на основе файловых потоков, для файловых потоковиспользуется класс FileStream. Класс FileStream позволяет выполнять сфайлами данных большое количество действий, однако данный подходявляется достаточно низкоуровневым и здесь детально не рассматривается.Он детально рассмотрен в работах [1, 2]. Следует отметить, что данныйподход пришел в язык C# из стандартных библиотек языка Java.Для работы с бинарными файлами у класса File существуютупрощенные по сравнению с потоками методы чтения (ReadAllBytes) изаписи(WriteAllBytes).Ихможноприменятьдляобработкипоследовательности байтов.
Данные методы также можно использоватьдля бинарной сериализации/десериализации объектов, однако для этойзадачи существуют более эффективные классы, которые разобраны вследующем разделе. Рассмотрим более детально методы чтения и записитекстовых файлов.Метод File.ReadAllText возвращает считанный текстовый файл в видепеременной типа string. Метод File.WriteAllText записывает переменнуютипа string в качестве содержимого текстового файла.Для дальнейшей обработки текстовых файлов необходимо получатьпуть к файлу, расположенному в каталоге рядом с исполняемойпрограммой:/// <summary>/// Возвращает путь к текущему исполняемому файлу/// </summary>static string GetExecPath(){//Получение пути и имени текущего исполняемого файла//с помощью механизма рефлексииstring exeFileName =System.Reflection.Assembly.GetExecutingAssembly().Location;//Получение пути к текущему исполняемому файлуstring Result = Path.GetDirectoryName(exeFileName);return Result;}164Имя исполняемого файла получается с использованием механизмарефлексиикакимятекущейисполняемойсборки–System.Reflection.Assembly.GetExecutingAssembly().Location.
Далее методGetDirectoryName класса Path из полного имени каталога и файлавозвращает только имя каталога. Класс Path используется для действий сименами каталогов и файлов.Пример ввода строки и сохранения в файл://Текущий каталогstring currentPath = GetExecPath();Console.Write("Введите текст для записи в файл:");//Ввод содержимого файлаstring file1Contents = Console.ReadLine();//Формирование имени файлаstring file1Name = Path.Combine(currentPath, "file1.txt");//Запись строки в файлFile.WriteAllText(file1Name, file1Contents);//Чтение строки из файлаstring file1ContentsRead = File.ReadAllText(file1Name);Console.Write("Чтение строки из файла:");Console.WriteLine(file1ContentsRead);В данном примере содержимое строки вводится с клавиатуры, затем спомощью метода File.WriteAllText записывается в текстовый файл. Дляформирования имени файла используется метод Path.Combine, корректносоединяющий строку пути к текущему исполняемому файлу и имясоздаваемоготекстовогофайла.Еслиуказанныйтекстовыйфайлсуществует, то метод File.WriteAllText удаляет предыдущее содержимоефайла, а метод File.ReadAllText возвращает считанный текстовый файл ввиде строки.
В данном примере файл содержит только одну строку, однакометод File.ReadAllText может считать текстовый файл большого размера,содержащий произвольное количество переводов строк.Результаты вывода в консоль:Введите текст для записи в файл: пример текстаЧтение строки из файла: пример текста165При этом в каталоге, содержащем исполняемый файл, действительносоздается текстовый файл file1.txt с указанным содержимым.В классе File также есть методы, способные записать (WriteAllLines)или прочитать (ReadAllLines) массив строк.Пример использования методов для чтения и записи строк:Console.WriteLine("Введите строки для записи в файл (пустая строка окончание ввода):");string tempStrTrim = "";//Список строкList<string> list = new List<string>();do{//Временная переменная для хранения строкиstring tempStr = Console.ReadLine();//Удаление пробелов из введенной строкиtempStrTrim = tempStr.Trim();if (tempStrTrim != ""){//Непустая строка сохраняется в списокlist.Add(tempStrTrim);}}while (tempStrTrim != "");//Формирование имени файлаstring file2Name = Path.Combine(currentPath, "file2.txt");//Запись в файл массива строкFile.WriteAllLines(file2Name, list.ToArray());//Чтение строк из файлаstring[] file2ContentsRead = File.ReadAllLines(file2Name);Console.WriteLine("Чтение строк из файла:");foreach (string str in file2ContentsRead){Console.WriteLine(str);}Для хранения строк при вводе используется обобщенный список.Ввод строк осуществляется с помощью цикла с постусловием, в условиипроверяетсявводпустойстроки.Такимобразом,вводстрокосуществляется до ввода пустой строки.
Для введенной строки сиспользованием метода Trim удаляются пробелы в начале и конце строки.Если строка не является пустой, то она добавляется в список.166В данном примере для проверки пустоты строки выполняетсясравнение с пустой строкой (tempStrTrim != ""). Данный метод работаеткорректно с учетом того что для переменной tempStrTrim с помощьюметода Trim предварительно удалены пробелы в начале и конце строки. Нодля решения данной задачи в .NET также существует статический методкласса string – String.IsNullOrWhiteSpace(строка), возвращающий истину,если строка пуста или содержит только пробелы.ДлязаписивфайлмассивастрокприменяетсяметодFile.WriteAllLines, список строк преобразуется в массив с использованиемметода list.ToArray.ДлячтенияизфайламассивастрокиспользуетсяметодFile.ReadAllLines, для вывода прочитанных строк применяется циклforeach.Результаты вывода в консоль:Введите строки для записи в файл (пустая строка - окончаниеввода):строка1строка2строка3Чтение строк из файла:строка1строка2строка3При этом в каталоге, содержащем исполняемый файл, действительносоздается текстовый файл file2.txt с указанным содержимым.На практике для чтения текстового файла обычно используют методFile.ReadAllText, а далее текстовый файл, считанный в виде строки, делятна подстроки с помощью метода string.Split.
Метод Split позволяетразделить строку на подстроки с помощью произвольного разделителя,167которым может быть символ переноса строки (в этом случае возвращаетсямассив строк текстового файла) или пробел (в этом случае возвращаетсямассив слов текстового файла).7.3 Сериализация и десериализация объектовОдной из наиболее частых задачей, возникающих при работе сфайлами, является сохранение в файл или чтения из файла объектовклассов.Задача сохранения объекта называется сериализацией, а задача чтения– десериализацией. В результате сериализации получается «твердая копия»объекта в виде файла, которая может быть куда-либо сохранена,перемещена и т.д.
В результате десериализации объект восстанавливаетсяна основе «твердой копии», и с ним можно продолжить работу.Внастоящеевремянаиболеечастодлясериализацииидесериализации используется база данных. В .NET существует технологияEntityFramework,котораяобеспечиваетобъектно-реляционноеотображение (object-relational mapping – ORM) между объектами классовязыка C# и записями в таблице реляционной базы данных.
ФактическиEntity Framework решает задачи сериализации и десериализации объектовклассов языка C# в таблицы реляционной БД. Также Entity Frameworkрешает множество других задач, в том числе облегчение разработкизапросов к данным с помощью технологии LINQ to Entities.В данном разделе на основе фрагментов примера 13 рассмотренынаиболее простые методы сериализации и десериализации объектов вфайлы. Классы, используемые для решения данной задачи, расположены впространстве имен System.Runtime.Serialization.1687.3.1 Бинарная сериализация и десериализацияНаиболеечастоприменяютсябинарнаясериализацияидесериализация с использованием класса BinaryFormatter.Вначале создадим класс данных, для которого будет использованабинарная сериализация и десериализация:using System;namespace Serialization{[Serializable]class DataBin{public int int1 { get; set; }public double double1 { get; set; }public string str1 { get; set; }public override string ToString(){return"str1=" + str1+ " int1=" + int1.ToString()+ " double1=" + double1.ToString();}}}Класс содержит три свойства: строкового, целого и вещественноготипов.
Для класса перегружен метод ToString который выводит значениясвойств в строковом формате. Для использования бинарной сериализацииклассобязательнодолженбытьпомеченатрибутом[Serializable](применение атрибутов разобрано далее в разделе рефлексии).Пример создания объекта для сериализации:DataBin b = new DataBin(){str1 = "строка1",int1 = 333,double1 = 123.45};Следует обратить внимание, что объект класса создается не совсемобычным способом – вначале вызывается пустой конструктор класса169DataBin, а потом ставятся фигурные скобки и происходит инициализациясвойств класса, которые разделяются запятыми.
Такой синтаксис созданияобъектов класса допустим начиная с .NET 4.0. При такой формеинициализации пустые скобки при вызове конструктора можно не ставить,как показано в следующем примере.Пример создания объекта для сериализации без использования скобокпри вызове конструктора:DataBin b = new DataBin{str1 = "строка1",int1 = 333,double1 = 123.45};Пример сериализации объекта:Console.WriteLine("До сериализации:");Console.WriteLine(b);//Текущий каталогstring currentPath = GetExecPath();//Формирование имени файлаstring fileBinName = Path.Combine(currentPath, "file1.bin");//При сериализации файл необходимо открыть с использованием потоковStream TestFileStream1 = File.Create(fileBinName);//Создание объекта класса сериализацииBinaryFormatter serializer = new BinaryFormatter();//Cериализация объекта в файлserializer.Serialize(TestFileStream1, b);//Закрытие потокаTestFileStream1.Close();Сначала выводится в консоль сериализуемый объект в строковомвиде.
Далее формируется имя файла для сериализации в переменнойfileBinName.Для сериализации необходимо открывать файл с использованиемпотоков. Файл открывается в режиме записи с помощью метода File.Create.После завершения работы с потоком следует закрыть поток посредствомметода Close.Сериализация и десериализация осуществляются с использованиемобъекта serializer класса BinaryFormatter. Для сериализации используется170метод Serialize, которому в качестве параметров передаются открытыйпоток для записи и сериализуемый объект.Пример десериализации объекта://Открытие файла в виде потока на чтениеStream TestFileStream2 = File.OpenRead(fileBinName);//Десериализация объектаDataBin b2 = (DataBin)serializer.Deserialize(TestFileStream2);//Закрытие потокаTestFileStream2.Close();Console.WriteLine("После десериализации:");Console.WriteLine(b2);Для десериализации также нужно открывать файл с помощьюпотоков.















