Смекни!
smekni.com

Основы алгоритмизации и программирования 2 (стр. 30 из 32)

Как это работает

Запись данных в файл с произвольным доступом

Данное приложение открывает файл в своей собственной директории и записывает в него несложную строку. Все это происходит аналогично предшествующему примеру.

Следующая строка создает символьный массив с помощью статического метода ToCharArray () класса String. Поскольку в С# все можно рассматривать в качестве объекта, а текст "Hello world" на самом деле представляет собой объект string, то эти методы могут вызываться даже для обычной строки символов:

charData = "Hello World" .ToCharArray() ;

Из следующих строк становится понятным, каким образом можно преобразовать массив символов в соответствующий массив байтов, который требуется объекту FileStream.

Encoder e = Encoding. UTF8.GetEncoder();
е.GetBytes(charData,0,charData.Length, byDate, 0,true;

На этот раз мы создаем объект Encoder, который также основывается на кодировке UTF8. В данном случае для выполнения перекодировки также используется кодировка Unicode, однако на этот раз нам необходимо перекодировать символьные данные в корректный байтовый формат, прежде чем у нас появится возможность записать информацию в поток. Это совершается в методе GetBytes (). В нем происходит преобразование символьного массива в байтовый. Этому методу в качестве первого параметра передается символьный массив, а в качестве второго – индекс элемента, с которого следует начинать преобразование. В качестве третьего параметра этому методу передается количество символов, подлежащих преобразованию; в качестве четвертого – байтовый массив, в котором должна размещаться информация после преобразования, и в качестве пятого – индекс элемента, с которого начинается заполнение байтового массива. Последний параметр определяет, должен ли объект Encoder обновлять свое состояние после окончания работы. Это имеет отношение к тому факту, что объект Encoder сохраняет в памяти то место, на котором была прекращена запись в байтовый массив Это оказывается весьма полезным при осуществлении последовательных обращений к объекту Encoder, но оказывается совершенно бессмысленным в случае единственного обращения к нему. При завершающем обращении к объекту Encoder этому параметру должно быть присвоено значение true, означающее, что память должна быть очищена, а объект освобожден для процедуры сборки мусора.

После выполнения всех этих действий запись байтового массива в объект FileStream посредством метода Write() не представляет никаких трудностей:

aFile.Seek(0,SeekOrigin.Begin);
aFile.WritetbyData,0,byData.Length);

8.2.Объект StreamWriter

Работа с объектом FileStream достаточна сложна, поэтому может возникнуть вопрос, нет ли какого-либо более простого способа. Обычно вся работа с объектом FileStream оказывается скрытой от пользователя за счет работы с объектами StreamWriter и StreamReader и использования их методов для выполнения манипуляций над файлами. Если перед вами не стоит задача перемещать указатель файла на произвольную позицию, то здесь эти классы позволяют значительно упростить работу с файлами. Класс StreamWriter позволяет осуществлять запись в файл символов и строк, он самостоятельно выполняет все необходимые преобразования и производит запись в объект FileStream.

Существуют разнообразные способы создания экземпляров класса StreamWriter. Если уже имеется объект FileStream, то можно воспользоваться им для создания объекта StreamWriter:

FileStream aFile = new FileStream("Log. txt" ,FileMode.CreateNew) ;
StreamWriter sw = new StreamWriter(aFile);

Объект StreamWriter может также создаваться непосредственно из файла:

StreamWriter sw = new StreamWriter("Log.txt",true);

Этот конструктор принимает в качестве параметров имя файла и логическое значение, которое указывает на то, следует ли добавлять информацию к уже существующему файлу или необходимо создать новый. Если это значение равно false, то либо происходит создание нового файла, либо из существующего файла сначала удаляется все хранящаяся в нем информация, а затем он открывается на запись. Если же это значение равно true, то файл просто открывается, а все хранящаяся в нем информация сохраняется. Если такого файла не существует, то создается новый файл.

Обратите внимание на то, что здесь нет такого широкого спектра возможностей, как при создании объекта FileStream. Кроме логического значения, определяющего, следует ли добавлять информацию к уже существующему файлу или создавать новый файл, нег никаких других опций, например, отсутствует возможность задания свойства FileMode, которое мы уже задавали при работе с классом FileStream. Точно так же отсутствует возможность задания свойства FileAccess, поэтому вы всегда будете обладать доступом к файлу на чтение/запись. Для того чтобы воспользоваться какой-либо из этих возможностей, следует сначала обратиться к конструктору класса FileStream, а затем создать объект StreamWriter на основе объекта FileStream.

ПРАКТИКУМ. Выходной поток

1. Создайте новый проект. Выберите пункт меню С# Console Application и назовите его StreamWrite.

2. В данном случае опять придется воспользоваться пространством имен System.IO, поэтому добавьте соответствующую строку в начало файла Classl.cs.

using System;
using System.IO;

3. Добавьте следующий код в метод Main():

static void Main(string[] args) { try

{

FileStream aFile = new FileStream("Log.txt",FileMode.OpenOrCreate) ;

StreamWriter sw = new StreamWriter(aFile) ;

// Запись данных в файл sw.WriteLinet("Hello World"); sw.Write("This is a") ; sw.Write("string of characters."); sw.Closed ; } catch(IOException e) {

Console. WriteLine("An IO exception has been thrown!");

Console.WriteLine(e.ToString());

Console.ReadLine() ; return; } return; }

4. Постройте проект и запустите его. Если в нем не будет обнаружено никаких ошибок, то он очень быстро выполнится и закроется. Поскольку мы не предусмотрели вывода на консоль, то наблюдать за работой этой программы оказывается не очень интересно.

5. Перейдите в директорию приложения и найдите там файл Log.txt. Он должен располагаться в папке StreamWriter\bin\Debug, поскольку используется относительный путь. Как это работает – Выходной поток

Данное простое приложение демонстрирует работу двух наиболее важных методов класса StreamWriter – Write () и WriteLine(). У каждого из них имеется большое количество перегружаемых версий, позволяющих использовать различные сложные возможности при выводе в файл, однако в настоящем примере мы воспользовались основной возможностью вывода строки.

Метод WriteLine () осуществляет запись переданной строки, за которой немедленно следует символ новой строки. Как мы можем видеть в настоящем примере, это приводит к тому, что следующая операция записи выполняется с новой строки. Метод Write() просто записывает передаваемую ему строку в файл, не добавляя символа перехода к новой строке. Это позволяет осуществлять запись целого предложения или абзаца с помощью нескольких обращений к методу Write ().

8.3.Форматирование данных

Точно так же, как существует возможность вывода данных в отформатированном виде на консоль, так и в файл мы можем записывать отформатированные данные. Для этого применяются те же методы – Write () и WriteLine(), но в этом случае им могут передаваться параметры, определяющие характер форматирования. Например:

sw.WriteLine("The Date is {0}", System.DateTime.Now.ToShortDateString());
sw.Write("{0}, {1}, {2}", "Kay", "Dan", "Rob");

В данном примере вы можете увидеть, каким образом осуществляется запись файлов, разделенных запятыми. В более сложных примерах данные могут поступать из объекта DataSet и других источников.

8.4.Объект StreamReader

Входные потоки используются для считывания данных, хранящихся во внешних источниках. В большинстве случаев таким источником является дисковый файл или сетевой адрес. Однако не следует забывать, что в качестве такого источника может использоваться любой объект, отправляющий данные, например, сетевое приложение, web-служба и даже консоль.

Для чтения данных мы будем использовать класс StreamReader. Так же, как и класс StreamWriter, класс StreamReader является общим классом, который может использоваться для любого потока. Мы снова будем создавать его на базе объекта FileStream, поэтому он будет ссылаться на нужный нам файл.

Объекты StreamReader создаются способом, напоминающим способ создания объектов StreamWriter. Наиболее распространенный способ создания таких объектов заключается в использовании заранее созданного объекта FileStream:

FileStream aFile = new FileStream("Log. txt".FileMode.Open);
StreamReader sr = new StreamReader(aFile);

Так же, как и класс StreamWriter, StreamReader может создаваться непосредственно на основе строки, в которой содержится путь к конкретному файлу:

StreamReader sr = new StreamReader("Log.txt") ;

ПРАКТИКУМ. Выходной поток

1. Создайте новый проект. Выберите пункт меню С# Console Application и назовите его StreamRead.

2. В данном случае нам опять потребуется импортировать пространство имен System.IO, поэтому добавьте соответствующую строку в начало файла Class1.cs.

using System;
using System.IO;

3. Добавьте следующий код в метод Main ():

static void Main (string[] args) { string strLine, try

{

FileStream aFiie = new FileStream("bog. txt",FileMode.Open);

StreanReader sr = new StreamReader(aFile); strLine = sr ReadLine () ;

//Построчное считывание данных while(strLine !=null)

{

Console.WriteLine(strLine) ;

strLine = sr. ReadLine ();

}

sr.Close() ;

Console.ReadLine(); } catch(IOException e) {

Console. WriteLme ("An IO exception has been thrown!");

Console.WriteLine(e.ToString());

Console.ReadLine(); return; } return; }

4. Создайте в директории StreamReader\bm\Debug файл Log. txt.

Это может быть совершенно новый файл или скопированный регистрационный файл, созданный в предыдущем примере. Убедитесь, что файл находится в той же директории, что и приложение.