Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторная работа 10.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
143 Кб
Скачать
☆

Классы TextWriter и StreamWriter

Абстрактный класс TextWriter содержит методы, позволяющие производить запись символов в байтовый поток (файл). Основные методы приведены в таблице 10.2.

Таблица 10.2

Методы класса TextWriter

Название

Описание

Close()

Закрывает файл, освобождает связанные с ним ресурсы

Write()

Осуществляет запись данных в текстовый поток. Метод позволяет принимать в качестве параметра данные, представленные в разных форматах (целые или вещественные числа, символы или массивы символов, строки, логические переменные)

WriteLine()

Записывает в текстовый поток данные, за которыми следует признак конца строки

Класс StreamWriter является классом-наследником класса TextWriter и реализует методы класса-предка.

Конструктор StreamWriter(<ИмяФайла>) создает текстовый поток для записи данных в заданный файл. Отметим, что имя файла может быть задано с указанием пути либо без него. Если файл существует, он будет перезаписан, в противном случае создается новый файл.

Рассмотрим использованием описанных методов на простом примере: вывести значения одномерного массива в файл. Напишем метод WriteToFile(), реализующий вывод элементов массива в заданный файл. Исходя из условия задачи, метод будет принимать в качестве параметров, во-первых, имя заданного файла FileName, во-вторых, одномерный массив MyArray.

static void WriteToFile(string FileName, int[] MyArray)

{

using (StreamWriter OutputFile = new StreamWriter(FileName))

{

foreach (int element in MyArray)

OutputFile.Write("{0} ", element);

}

}

Здесь мы создаем экземпляр класса StreamWriter с именем OutputFile для заданного файла, в цикле foreach последовательно просматриваем все элементы заданного массива и записываем их в файл с помощью метода Write().

Основная программа включает в себя описание массива с инициализацией и вызов метода WriteToFile().

static void Main(string[] args)

{

int[] MyArray = {1, 22, 13, -4, 5, 16, 27, 18, -9};

WriteToFile("output.txt", MyArray);

}

Отметим, что в рассмотренном примере значения одномерного целочисленного массива MyArray будут записаны в файл через пробел. Имя файла задано без указания пути к файлу, поэтому, чтобы просмотреть результаты работы программы, необходимо открыть файл “output.txt”, который находится в каталоге “…\bin\debug\” текущего решения.

Классы Stream и FileStream

Класс Stream является абстрактным базовым классом всех потоков. При работе с потоком допустимы три основные операции:

  • чтение из потока – перенос информации из потока в структуру данных, такую как массив байтов;

  • запись в поток – передача данных из структуры данных в поток;

  • поиск, включающий в себя отправку запросов и изменение текущей позиции внутри потока.

Некоторые свойства и методы класса Stream приведены в таблице 10.3.

Таблица 10.3

Свойства и методы класса Stream

Название

Вид

Описание

CanRead

неизменяемое свойство

Показывает, можно ли ввести данные из потока

CanWrite

неизменяемое свойство

Показывает, можно ли записать данные в поток

CanSeek

неизменяемое свойство

Показывает, поддерживает ли поток произвольный доступ к данным, при котором можно задать текущее положение в потоке

Close()

экземплярный метод

Закрывает текущий поток и освобождает все связанные с ним ресурсы

Flush()

экземплярный метод

Записывает данные из буфера в связанный с потоком источник данных (файл) и очищает буфер

Length

неизменяемое свойство

Возвращает длину потока в байтах

Position

изменяемое свойство

Возвращает либо задает текущее положение в потоке

Read()

экземплярный метод

Считывает последовательность байтов определенной длины из потока и записывает их в одномерный массив байт. Возвращает количество прочитанных байтов либо ноль, если достигнут конец потока

ReadByte()

экземплярный метод

Возвращает целочисленное представление следующего байта из потока либо –1, если достигнут конец потока

ReadTimeOut

изменяемое свойство

Возвращает или задает продолжительность времени ожидания в миллисекундах в процессе чтения данных из потока

Seek()

экземплярный метод

Перемещает указатель текущего положения в потоке на заданную позицию

Write()

экземплярный метод

Записывает последовательность байт определенной длины в массив, начиная с указанного индекса, и перемещает указатель в потоке на количество записанных байт

WriteByte()

экземплярный метод

Записывает один байт в поток и перемещает указатель в потоке на один байт

WriteTimeOut

изменяемое свойство

Возвращает или задает продолжительность времени ожидания в миллисекундах в процессе записи данных в поток

Ввод/вывод, организованный на уровне байтов, называется байтовым потоком. Для создания байтового потока служит класс FileStream, являющийся классом-наследником класса Stream и реализующий рассмотренные выше методы и свойства. Конструктор класса перегружен и имеет несколько вариантов реализации, мы рассмотрим только одну из них. FileStream(<ИмяФайла>,<Режим>,<ТипДоступа>)- создает экземпляр класса FileStream, связывает его с заданным файлом и открывает файл в заданном режиме с заданным типом доступа. Поясним, что любой файл можно открывать в различных режимах. При этом режим открытия файла задается одним из константных значений перечисления FileMode:

  • Append – указывает, что операционная система (ОС) должна открыть существующий файл для записи, при этом текущий указатель положения в файле устанавливается в конец файла. Если файл не существует, создает новый файл;

  • Create – указывает, что ОС должна создать новый файл. Если в каталоге уже существует файл с заданным именем, он будет переписан;

  • CreateNew – указывает, что ОС должна создать новый файл. Если в каталоге уже существует файл с заданным именем, генерируется исключение IOException;

  • Open – указывает, что ОС должна открыть существующий файл. Если файл с заданным именем не существует, генерируется исключение FileNotFoudException;

  • OpenOrCreate – указывает, что ОС должна открыть файл с заданным именем, если он существует, либо создать файл с заданным именем в противном случае;

  • Truncate – указывает, что ОС должна открыть существующий файл. После открытия он должен быть обрезан до нулевой длины. Файл может быть открыт только для записи.

Кроме режима открытия фала, в конструкторе необходимо указать тип доступа к нему. Этот параметр принимает одно из константных значений перечисления FileAccess:

  • Read – указывает, что файл открыт только для чтения;

  • Write – указывает, что файл открыт только для записи;

  • ReadWrite – указывает, что файл доступен и для чтения и для записи.

Приведем простой пример использования байтовых потоков для записи данных в файл и считывания данных из файла.

try

{

FileStream InputFile = new FileStream("input.txt", FileMode.Create, FileAccess.Write);

for (byte i = 0; i < 100; i++)

InputFile.WriteByte(i);

InputFile.Close();

}

catch

{

Console.WriteLine("Ошибка ввода");

}

Здесь мы создаем файл “input.txt” и открываем его для записи. Далее записываем в него целые числа от 0 до 99. Важно заметить, что при открытии созданного текстового файла вы не увидите числа от 0 до 99. Это связано с тем, что данные записаны в файл на уровне байт, и не преобразованы в символьный формат, удобный для восприятия человеком.

В следующем примере мы открываем созданный файл “input.txt” для чтения и выводим считанные данные на экран.

try

{

FileStream InputFile = new FileStream("input.txt",

FileMode.Open, FileAccess.Read);

int b = InputFile.ReadByte();

while (b != -1)

{

Console.WriteLine(b);

b = InputFile.ReadByte();

}

InputFile.Close();

}

catch

{

Console.WriteLine("Ошибка чтения файла");

}

В результате работы программы на экран будет выведена последовательность чисел от 0 до 99.

Используя метод Seek() для позиционирования указателя текущего положения в файле, можно управлять процессом считывания данных из файла. Синтаксис: Seek(long offset, SeekOrigin origin). Здесь параметр offset задает смещение в байтах относительно точки отсчета положения в потоке. Точка отсчета задается параметром origin и может принимать одно из константных значений перечисления SeekOrigin: Begin – начало файла, Current – текущее положение, End – конец файла.

Следующая модификация рассмотренного выше примера, используя метод Seek(), считывает лишь каждый третий байт из потока.

try

{

FileStream InputFile = new FileStream("input.txt",

FileMode.Open, FileAccess.Read);

int b = InputFile.ReadByte();

while (b != -1)

{

Console.WriteLine(b);

InputFile.Seek(2, SeekOrigin.Current);

b = InputFile.ReadByte();

}

InputFile.Close();

}

catch

{

Console.WriteLine("Ошибка чтения файла");

}

Подчеркнем, что байтовый поток удобно использовать только для решения задач, в которых операции с файлами реализуются программным путем и пользователю не требуется самому изменять содержимое файлов. Если же необходимо считать из файла данные, введенные пользователем и представленные в символьном формате, удобнее пользоваться классами StreamReader и StreamWriter. Напомним, что эти классы, по сути, являются лишь надстройкой над классом Stream, они тоже используют байтовые потоки для чтения данных из файла и записи данных в файл, но при этом выполняют автоматическое преобразование байтового потока в символьный и наоборот (рис. 10.4).

Рис. 10.4. Байтовый и символьный потоки