TextReader, TextWriter и производные классы
Двоичные потоки чтения/записи хорошо подходят для случаев, когда программисту точно известен порядок следования данных в двоичном формате, но прочитать полученный файл бывает непросто. Таким образом, для хранения обычного текста в файле лучше поискать другой вариант. В этой стандартной ситуации вместо пары BinaryReader/BinaryWriter следует использовать пару StreamReader/StreamWriter. По функциональным возможностям классы StreamReader и StreamWriter близки к традиционным средствам последовательного доступа к файлам из прежних версий VB (если не считать того, что в этих классах появилась поддержка Unicode). В классе StreamReader помимо метода Read также имеется удобный метод ReadToEnd, позволяющий прочитать весь файл за одну операцию.
Обратите внимание, что эти классы объявлены производными от абстрактных классов TextReader и TextWriter, а не от Stream. Эти абстрактные классы, объявленные с атрибутом Must Inherit, содержат общие средства чтения/записи текста. Их методы перечислены в табл. 9.11 и 9.12.
Таблица 9.11. Основные методы класса TextReader
Метод |
Описание | ||||
Close | Закрывает существующий поток TextReader и освобождает все системные ресурсы, связанные с ним | ||||
Peek |
Возвращает следующий символ в потоке без смещения указателя текущей позиции | ||||
Read | Читает один символ из входного потока. Перегруженная версия читает в символьный массив определенное количество символов начиная с заданной позиции | ||||
ReadLine | Читает символы до комбинации CR+LF и возвращает их в виде строкового значения. Если текущая позиция находится в конце файла, метод возвращает Nothing | ||||
ReadToEnd | Читает все символы от текущей позиции до конца TextReader и возвращает их в виде одной строки (метод особенно удобен при работе с небольшими файлами) | ||||
Таблица 9.12. Основные методы класса TextWriter
Метод |
Описание | ||||
Close | Закрывает существующий поток TextWriter и освобождает все системные ресурсы, связанные с ним | ||||
Write | Перегруженные версии метода позволяют записывать в поток любые базовые типы данных в текстовом формате | ||||
WriteLine | Перегружается для записи в поток любых базовых типов данных в текстовом формате, за которыми записывается комбинация CR+LF | ||||
Свойства Console.In и Console.Out используемые при консольном вводе-выводе, в дей- ствительности являются экземплярами классов TextReader и TextWriter. Методы Соп-sole.Setln и Console.SetOut позволяют перенаправить стандартный ввод и вывод любым классам *Reader и 'Writer соответственно.
Поскольку классы TextReader и TextWriter являются абстрактными, программы работают с конкретными реализациями StreamReader и StreamWriter. Как и в случае с классами BinaryReader и BinaryWriter, при создании объектов StreamReader и StreamWriter конструктору обычно передается существующий объект потока:
myFile = New FileStreamtfileName.FileMode.Open, FileAccess.Read)
textFile= New StreamReader(myFile)
Для получения объекта также можно воспользоваться методами класса File. Пример неявного создания объекта StreamReader при создании файлового потока продемонстрирован ниже:
Dim aStreamReader As StreamReader
aStreamReader = File.OpenText ("sample.txt")
Объекты класса StreamWriter создаются аналогичным образом:
Dim aStreamWriter As StreamWriter
aStreamWriter = File.CreateText ("test.txt")
Данные записываются в поток методами Write и WriteLine. Что касается чтения, в вашем распоряжении два способа. В наиболее распространенном варианте программа в цикле читает строки до тех пор, пока очередная прочитанная строка не окажется равной Nothing. В программе это выглядит примерно так:
Dim s As String Do
s = theStreamReader.ReadLine If Not s Is Nothing Then
' Выполнить нужные действия с s.
' Например, вызвать Console.WriteLine(s).
End If
Loop Untils Is Nothing
Также можно воспользоваться методом Peek и проверить, равен ли следующий читаемый символ -1 (признак конца файла):
Do Until theStreamReader.Peek = -1
В качестве примера использования класса TextReader ниже приводится простая процедура, предназначенная для вывода текстового файла на экран. Обратите внимание: в строках 5-17 весь важный код заключен в блок Try-Catch-Finally. В этом блоке программа пытается закрыть открытый поток независимо от того, что произошло при операциях с ним.
Как упоминалось выше, перед вызовом Cl ose в строке 16 сначала необходимо убедиться в том, что поток был успешно создан. Также обратите внимание на то, как в строке 14 к инициируемому исключению добавляется содержательное сообщение. В реальной программе следовало бы определить новый класс исключения (за подробностями обращайтесь к главе 7).
1 Sub DisplayTextFile(ByVal fName As String)
2 Dim myFile As FileStream
3 Dim textFile As StreamReader
4 Dim stuff As String
5 Try
6 myFile = New FileStream(fName.FileMode.Open, FileAccess.Read)
7 textFile = New StreamReader(myFile)
8 stuff = textFile.ReadLine()
9 Do Until stuff Is Nothing
10 Console.WriteLine(stuff)
11 stuff = textFile.ReadLine()
12 Loop
13 Catch e As Exception
14 Throw New Exception("If the file existed.it was closed")
15 Finally
16 If Not (myFile Is Nothing)Then myFile.Close()
17 End Try
18 End Sub
19 End Module
В общем случае отдельные строки файла можно сохранить в динамическом массиве ArrayList (если, конечно, количество строк относительно невелико). Для этого достаточно внести минимальные изменения в предыдущую программу. В заголовок процедуры добавляется новый параметр:
Sub DisplayTextFile(ByVal fName As String,ByVal where As ArrayList)
Строка 10 приводится к следующему виду:
where, Add(stuff)