Использование классов StreamReader, StreamWriter и объекта My.Computer.FileSystem для работы с текстовыми файлами

Тема 10

Создание приложений с потоковыми файлами

 

 

Основные понятия

 

 

Использование классов StreamReader, StreamWriter и объекта My.Computer.FileSystem для работы с текстовыми файлами

 

 

Примеры создания проектов (приложений),

Работающих с потоковыми файлами

 

 

Тестовые задания

 

 

4.10.7. Лабораторная работа по теме «Создание приложений, работающие с потоковыми файлами»

 

 

4.10.7.1.Контрольные вопросы

 

Основные понятия

 

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

Файл это поименованная совокупность любых данных, размещенная на внешнем запоминающем устройстве, хранимая, пересылаемая и обрабатываемая как единое целое. Файл может содержать программу, числовые данные, текст, закодированное изображение и пр. Физически файлы реализуются как участки памяти на внешних носителях, например, на магнитных дисках или CD-ROM. Каждый файл должен иметь имя.

К файловой системе имеет доступ любая прикладная программа, для этого во всех языках программирования, в том числе и в VB, имеются специальные средства в виде методы классов .NET Framework для работы с файлами.

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

Текстовые файлы состоят из одной или более строк, слов или симво­лов. Обычные текстовые файлы определены в MS Windows как Текстовые документы и имеют расширение *.txt.

Работа с любым файлом, в том числе с текстовыми файлами, состоит из трех этапов:

· открытие файлов;

· чтение или запись информации из файла или в файл;

· закрытие файла.

 

Поток – это программный виртуальный канал для обмена данными между приложением и Windows или другим приложением. При взаимодействии приложения с Windows потоки, как правило, используются для работы с устройствами и представляют собой абстрактный уровень между приложением и устройством, что позволяет скрыть от приложения низкоуровневый механизм доступа к устройствам, упростить и унифицировать процесс написания программ, использующих ввод/вывод. Поток представляется программисту как логическое устройство приема-передачи информации. Потоки бывают входные и выходные. Данные, поступающие в поток, как правило, буферизуются, т.е. помещаются в специальный буфер данных, в котором они могут храниться. Передача данных из буфера получателю данных происходит при запросе от получателя или в случае заполнения буфера данных. Если получатель производит чтение данных, когда буфер потока пуст, то данная ситуация расценивается как достижение конца потока.

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

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

Грубо обобщая, можно разделить функции ввода/вывода в каркасе .NET Framework на две широкие категории, не зависящих от устройства хранения данных – это запись и чтение.

Данные могут рассматриваться как поток байтов или символов. Данные также можно рассматривать как набор объектов.

КлассStream(Поток, Абстрактный файл) – абстрактный класс, который является базовым для чтения и записи байтов в некоторое хранилище данных типа файла. Этот класс поддерживает синхронные и асинхронные чтение и запись. Асинхронные методы обсуждаются ниже в данной главе.

КлассFileStream, который является производным от классаStream, предоставляет операции чтения и записи последовательности байтов в файл. КонструкторFileStreamсоздает экземпляр потока. Перегруженные методы классаStream(Поток, Абстрактный последовательный файл) осуществляют чтение и запись в файл.

Для загрузки в текстовое поле или строку содержимого текстового файла, а также для записи строковых данных в файл в VB можно использовать потоковый доступ:

· с использованием методов класса System.IO библиотеки
Framework.NET;

· с использованием объекта My.Computer.System.

 

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

Рассмотрим средства VBдля обработки ошибок времени выполнения.

Ошибки времени выполнения (также называемые исключениями) возникают при исключительных условиях работы - например, из-за отсутствия диска в дисководе или неправильного заданного пути при открытии файла. Блоки кода, обрабатывающие такие ошибки, называются структурными обработчиками ошибок (или структурными обработчиками исключений). Их можно использовать для распознавания ошибок времени исполнения при их возникновении в программе и настройки программы так, что она снова сможет получить управление и продолжить работу. Для этого имеется блок Try…Catch…End Try – синтаксическая конструкция VB для обработки ошибок.

Ошибка времени исполнения возникает тогда, когда VB пытается выполнить оператор, который по какой-то причине не может быть выполнен в том виде, в котором он написан. Это не значит, что VB недостаточно «умен», чтобы справиться с проблемой; это значит, что компилятору VB не сказали, что делать, если что-то пойдет не так.

Можно написать специальные процедуры VB, называемые структурными обработчиками ошибок, которые будут реагировать на ошибки времени исполнения. Обработчик ошибок отслеживает ошибку времени исполнения и говорит программе, как продолжать работу при возникновении этой ошибки. Обработчики ошибок помещаются в процедуры событий там, где существует возможность возникновения проблемы, или в общие функции или подпрограммы, специально предназначенные для обработки ошибок. Как предполагает их название, обработчики ошибок обрабатывают ошибку с помощью оператора Try…Catch…End Try и специального объекта отслеживания ошибок – экземпляра класса Exception. Например, если ошибка времени исполнения произошла при загрузке файла с диска, обработчик ошибок может отобразить собственное сообщение об ошибке, которое укажет на проблему.

Оператор Try необходимо поместить в процедуру события непосредственно перед оператором, в котором может произойти непредвиденная ситуация, а блок Catch следует непосредственно за ним и содержит операторы, которые необходимо выполнить, если произойдет ошибка времени исполнения. Также можно использовать некоторые дополнительные операторы, такие, как Finally, а также вложенные блоки кода Try…Catch…End Try. Базовый синтаксис обработчика исключений Try…Catch…End Try может иметь следующий формат:

 

Try Операторы, которые могут вызвать ошибку времени исполнения Catch Операторы, которые выполняются, если ошибка времени исполнения происходит Finally Дополнительные операторы, выполняемые независимо от возникновения ошибки End Try

 

где Try, Catch и End Try – это обязательные ключевые слова, а Finally и операторы, которые стоят за ним, необязательны.

В Примерах 4.10.2-1 и 4.10.2-2 продемонстрирована ситуация возникновения ошибки времени выполнения, связанная с открытием файла.

 

 

Использование классов StreamReader, StreamWriter и объекта My.Computer.FileSystem для работы с текстовыми файлами

 

В последних версиях VSиспользуется эффективный потоковый доступ к файлам, который является средством .NET Frameworkи определен в пространстве имен (библиотеке классов) System.IO.

Поток (Stream) в VS– это абстрактный тип Stream, который представляет последовательность символов, передаваемых в среду или из среды для хранения информации. Потоки позволяют считывать и записывать данные на запоминающее устройство, которое в нашем случае соответствует файлу. Поэтому над потоками в основном выполняются операции чтения (Read), записи (Write поиска (Seek), которые реализованы в классе System.IO.Stream. Причем большинство потоковых объектов выполняют буферизацию данных, которая позволяет значительно повысить эффективность операций ввода/вывода. При этом данные потока не записываются сразу на диск, когда производится запись в файл, а помещаются в буфер и затем сбрасываются на диск, когда поток закрывается.

Таким образом, потоки класса System.IO.Stream осуществляют управление файлами на уровне отдельных байтов. Чтобы сделать операции чтения и записи более эффективными, в пространстве имен System.IO имеются средства для открытия и отображения текстовых файлов. Так, например, имеются классы StreamReader и StreamWriter, а также объект My.Computer.FileSystem.

'Процедура чтения из текстового файла Sub readfile1(ByVal filename As String, ByRef p As String) 'создание потока для чтения из текстового файла Dim Rf As StreamReader Rf = New StreamReader(filename) Try p = Rf.ReadToEnd()'чтение текста из файла в p Rf.close()'закрытие потока Catch ex As Exception MsgBox("Невозможно прочитать данные из файла") End Try End Sub

Рис. 4.10.2-1. Программный код процедуры readfile1()

чтения из текстового файла

 

Чтобы использовать классы StreamReader и StreamWriter, в начале программного кода проека следует добавить оператор доступа к этим классам: Imports System.IO.

 

'Процедура построчного чтения данных из текстового файла, 'подсчета числа строк и формирования строки для вывода данных Sub readfile2(ByVal filename As String, _ ByRef n As Integer, ByRef p As String) 'создание потока для чтения из текстового файл Dim Rf As New StreamReader(filename) Dim line As String p = ""'строка с исходными данными n = 0'количество строк в файле Try Do While Not Rf.EndOfStream() 'пока не достигнут конец потока line = Rf.ReadLine( )'чтение строки из файла в line n = n + 1 : p = p & line & vbNewLine Loop Rf.Close() 'закрытие потока Catch ex As Exception MsgBox("Невозможно прочитать данные из файла") End Try End Sub

Рис. 4.10.2-2. Программный код процедура readfile2()

построчного чтения данных из текстового файла и подсчета числа строк

Класс StreamReader из библиотеки .NET Framework позволяет откры­вать в программе и отображать текстовые файлы.На рис. 4.10.2-1 и
рис. 4.10.2-2 представлены процедуры чтения содержимого всего текстового файла целиком в одну строку и построчного чтения данных из текстового файла. Обе эти процедуры имеют входной параметр filename (имя файла) и выходной параметр p (строка, содержащая значения, прочитанные из файла).

В примерах, представленных на рис. 4.10.2-1 и рис. 4.10.2-2, сначала создаются объекты Rf класса StreamReader – потоки открываются для чтения. Далее применяются методы созданных объектов: в примере на рис.4.10.3-1 метод ReadToEnd()считывает всю информацию из файла в строковую переменную p, начиная с текущей позиции (в данном примере с начала файла) и до конца файла; в примере на рис. 4.10.2-2 метод ReadLine()считывает из потока Rf только одну строку символов и присваивает ее содержимое строковой переменной line. Метод ReadLine()здесь применяется в цикле, пока не будет достигнут конец потока (endOfStream).

Метод Close() закрывает поток Rf и освобождает все ресурсы, которые были связаны с этим объектом.

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

На рис. 4.10.2-3 и рис. 4.10.2-4 представлены процедура записи всей строки в заново созданный текстовый файл, и процедура добавления строки в уже существующий файл. Обе процедуры в качестве входных параметров принимают filename и p–строка, содержимое которой записывается в файл.

 

' Процедура записи строки в заново созданный текстовый файл Sub writefile1(ByVal filename As String, ByVal p As String) 'проверка существования текстового файла с таким же именем If File.Exists(filename)Then MsgBox("Файл "&filename " уже существует") Exit Sub End If 'создание нового текст. файла и потока wf для записи в файл '1 способ Dim wf As StreamWriter = File.CreateText(filename) '2 способ Dim wf As New StreamWriter(filename) wf.WriteLine(p)'запись строки в файл wf.Flush()'очистка буфера потока wf.Close() 'закрытие потока End Sub

Рис. 4.10.2-3. Программный код процедура writefile1()

записи строки в заново созданный текстовый файл

'Процедура добавления строки в уже существующий текстовый файл ' Если такого файла нет, то он создается Sub writefile2(ByVal filename As String, ByVal p As String) 'проверка существования текстового файла с таким же именем If File.Exists(filename) = False Then MsgBox("Файл " & filename & " не существует") End If '1)Создание потока wf для добавления строки в конец файла 'Dim wf As StreamWriter = File.AppendText(filename) '2)Значение True 2-го параметра означает, что будет ' производиться дозапись в конец файла Dim wf As New StreamWriter(filename, True) wf.WriteLine(p)'запись строки в файл wf.Flush() 'очистка буфера потока wf.Close()'закрытие потока End Sub

Рис. 4.10.2-4. Программный код процедура writefile2()

добавления строки в уже существующий текстовый файл

 

При создании потока wf класса StreamWriter вторым способом может использоваться второй аргумент, который определяет способ записи данных в файл. Если этот аргумент равен True, то строка p добавляется в конец файла к уже существующему содержимому. Если второй аргумент равен False или отсутствует, то все содержимое файла (если оно существует) полностью стирается, и с начала файла записывается строка p.

 

Таблица 4.10.2-1

Объект Описание
My.Application Информация, связанная с текущим приложением, включая заголовок, директории, номер версии.
My.Computer Информация об оборудовании, программном обеспечении и файлах, имеющихся на текущем (локальном) компьютере. My.Computer включает My.Computer.FileSystem, который ис­пользуется для открытия текстовых файлов и зашифрованных файлов системы.
My.Forms Информация о формах текущего проекта VS.
My.User Информация о текущем активном пользователе из My.Computer.
My.WebServices Информация о веб-службах, активных в My.Computer, и ме­ханизм для доступа к новым веб-службам.

 

Пространство имен My– это средство быстрого доступа, которое упрощает доступ к .NET Framework при выполнении часто встречающихся задач, та­ких, как операции с формами, исследование содержимого компьютера и файловой системы, отображение информации о текущих приложениях или пользователях. С точки зрения пространства имен My выглядит примерно, как еще одна библиотека классов, которая дублирует в той или иной форме функциональность, уже присутствующую в .NET Framework.

Пространство имен My по функциональности разделено на несколько категорий, которые приведены в табл. 4.10.3-1.

Кроме того, пространство имен My это просто способ быстрого доступа к элементам .NET Framework, и все его возможности можно увидеть в окне Программный код при помощи технологии IntelliSense.

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

 

MsgBox(My.User.Name)

 

Эта строка осуществляет вывод, соответствующий рис. 4.10.2-5.

 

 

Рис. 4.10.2-5. Результат выполнения функции MsgBox(My.User.Name)

 

Объект My.Computer может отображать различную информацию о компьютере и его файлах. Например, следующий оператор отображает текущее системное время (локальная дата и время), определяемое ком­пьютером:

 

MsgBox(My.Computer. Clock. LocalTime)

 

Чтобы открыть существующий текстовый файл и вывести его содержимое в объект текстового поля, можно использовать объект My.Computer.FileSystem и метод ReadAllText( ).Программный код будет иметь вид, как на рис. 4.10.3-6.

Метод ReadAllText()копирует все содержимое указанного текстового файла в строковую переменную или объект (в данном случае, переменную с именем Str), что с точки зрения производительно­сти и времени написания кода быстрее, чем чтение файла по одной строке с помощью функции
LineInput().

 

'Процедура чтения данных из текстового файла 'целиком в одну строку и вывод данных в TextBox Sub vvodFile(ByVal filename As String, _ ByRef Str As String, ByRef T As TextBox) 'Открываем существующий файл и загружаем его текстовое 'содержимое целиком в одну строку Str Try Str = My.Computer.FileSystem.ReadAllText(filename) T.Text = Str Catch ex As Exception MsgBox("ошибка при чтении файла") End Try End Sub

 

Рис. 4.10.2-6. Программный код процедура vvodFile()

чтения данных из текстового файла целиком в одну строку

 

Метод ReadAllText()копирует все содержимое указанного текстового файла в строковую переменную или объект (в данном случае в переменную с именем Str), что с точки зрения производительно­сти и времени написания кода быстрее, чем чтение файла по одной строке с помощью функции
LineInput().

Благодаря этому фактору объект My.Computer.FileSystem предоставляет великолепный способ быстро запрограммировать часто встречающиеся задачи. Относительно этой новой функции и возможных способов ее применения важно отметить, что здесь объект My.Computer.FileSystem полезен потому, что читается весь текстовый файл. Однако функция LineInput( )и класс StreamReader предлагают боль­ше возможностей, чем реализация объекта My, и особенно это касается возможности обрабатывать файлы построчно. Эта возможность является очень важной при выполнении сортиров­ки и лексического разбора. Так что лучше всего знать все три метода открытия и создания текстовых файлов. Какой из них будет использоваться при программировании, зависит от ре­шаемой задачи и того, как ваш код будет использоваться.

Чтобы создать новый или добавить данные в существующий текстовый файл, можно использовать объект My.Computer.FileSystemи метод
WriteAllText( ).Программный код будет иметь вид, как на рис. 4.10.2-7.

В методе WriteAllText()третий аргумент определяет способ записи данных. Если указать True, то данные добавляются в конец, существующих данных файла; если же указать False, то в случае существования данных в файле они полностью заменяются новыми данными (файл перезаписывается).

 

'Процедура записи строки в текстовый файл Sub vivodFile(ByVal filename As String, ByRef Str3 As String) 'Запись строки-результата Str3 в текстовый файл; (False) 'параметра задает,что файл будет перезаписан. Try My.Computer.FileSystem.WriteAllText(filename, Str3, False) Catch ex As Exception MsgBox("ошибка при сохранении (создании) файла") End Try End Sub

 

Рис. 4.10.2-7. Программный код процедуры vivodFile()

записи строки в текстовый файл