![]() |
![]() |
![]() |
Важнейшие
члены классов FileSystemInfo, FileInfo и DirectoryInfo
Класс FileSystemlnfo
является базовым для классов Directorylnfo и Filelnfo и содержит большую часть
их общей функциональности. Перед нами хороший пример тех возможностей, которые
открываются при использовании абстрактных базовых классов. В классе Directory
Info существует метод GetFileSystemlnfos, который возвращает массив объектов
FileSystemlnfо, представляющих файлы и подкаталоги заданного каталога. Такое
становится возможным только благодаря существованию класса FileSystemlnfo. Важнейшие
члены базового класса FileSystemlnf о перечислены в табл. 9.4.
Таблица
9.4. Члены базового класса FileSystemInfo
Метод/свойство |
Описание |
||
Attributes (свойство) |
Атрибуты объекта.
Свойство доступно для чтения и записи |
||
CreationTime
(свойство) |
Время создания
объекта. Свойство доступно для чтения и записи |
||
Exists (свойство) |
Логический признак
существования файла или каталога |
||
Extension (свойство) |
Расширение файла |
||
FullName (свойство) |
Полное имя каталога
или файла |
||
LastAccessTime
(свойство) |
Дата/время последнего
обращения к объекту. Свойство доступно для чтения и записи |
||
LastWriteTime
(свойство) |
Время последней
записи в объект. Свойство доступно для чтения и записи |
||
Name (свойство) |
Для файлов —
имя файла. Для каталогов — имя последнего каталога в иерархии, если
это возможно. В противном случае возвращается полное имя |
||
Delete |
Удаляет объект |
||
Refresh |
Обновляет состояние
объекта |
||
В табл. 9.5
и 9.6 перечислены важнейшие методы класса DirectoryInfo и методы класса Filelnfo,
не имеющие непосредственного отношения к потокам (эта тема будет рассматриваться
позже).
Таблица
9.5. Основные методы класса DirectoryInfo
Метод/свойство |
Описание |
||
Exists (свойство) | Логический признак существования каталога | ||
Name (свойство) | Имя каталога | ||
Parent (свойство) | Объект DirectoryInfo для родительского каталога (для корневых каталогов возвращается Nothing) | ||
Create | Создает каталог, путь к которому указан в конструкторе DirectoryInfo | ||
CreateSubdirectory (ByVal As String) | Создает подкаталог, путь к которому передается в виде параметра. Возвращает объект Directorylnfo для созданного подкаталога | ||
Delete | Удаляет пустой каталог, представленный объектом Directorylnfo. Если присвоить True необязательному логическому параметру, происходит рекурсивное удаление непустого каталога и всех его подкаталогов | ||
GetDirectories | Возвращает массив объектов Directorylnfo для подкаталогов текущего каталога | ||
GetFiles |
Возвращает массив объектов Filelnfo для файлов текущего каталога |
||
GetFileSystemlnfos | Хороший пример использования абстрактных классов: метод возвращает массив объектов FileSystemlnfo, представляющих все файлы и подкаталоги текущего каталога | ||
MoveTo(ByVal destDirName As String) | Перемещает Directorylnfo и все его содержимое | ||
Root (свойство) | Объект DirectoryIlnfo для корневого каталога в иерархии текущего каталога | ||
Таблица
9.6. Члены класса Filelnfo, не возвращающие потоков
Метод/свойство |
Описание |
||
Directory (свойство) | Объект Directorylnfo для каталога, в котором находится файл | ||
DirectoryName (свойство) | Полный путь к файлу в строковом виде | ||
Exists (свойство) | Логический признак существования файла | ||
Length (свойство) | Размер текущего файла | ||
CopyTo(ByVal destFileName As String) |
Копирует существующий файл и возвращает объект Filelnfo для копии. Необязательный логический параметр управляет перезаписью существующих файлов | ||
Create | Создает файл по имени, указанному при конструировании объекта Filelnfo, и возвращает объект FileSystem для нового файла | ||
Delete | Удаляет файл, представленный объектом FileInfo | ||
MoveTo(ByVal destFileName As String) | Перемещает файл | ||
Идея
выделения общей функциональности в абстрактный базовый класс выглядит впол-не
логично, однако в данном случае она реализована не лучшим образом. Например,
свдйство Length присутствует в файле FileInfo, но не поддерживается в FileSystemlnfo,
поэтому для вычисления размера дерева каталогов приходится прибегать к услугам
другого объекта — а именно вызывать метод Size объекта Folder, входящего в
модель FileSystemObject. Эта модель впервые была представлена в VBScript,
поэтому в решение приходится включать ссылку на библиотеку сценарной поддержки
на базе СОМ.
Как упоминалось
во вступительной части, одной из целей проектирования класса System. I0.Stream
было абстрагирование примитивных операций при работе с потоками
байтов. В соответствий с этой концепцией каждая конкретная реализация класса
Stream должна предоставить свои версии следующих методов:
- Read — метод чтения
данных из потока. Иногда сводится к простейшему чтению одного байта, но во
многих производных классах используются сложные методы для чтения данных большими
порциями.
- Write — метод записи
данных в поток. Как и предыдущий метод, может сводиться к простейшей записи
одного байта, но может задействовать и фрагменты данных большего размера.
Впрочем,
этим возможности не ограничиваются. Кроме простого перемещения от первого байта
к последнему реализация класса Stream может поддерживать и другие способы —
например, перемещение в обратном направлении или непосредственный переход к
заданной позиции в потоке. Такое возможно для файловых потоков, но не имеет
смысла (а следовательно, и не реализуется) для потоков, основанных на сетевых
соединениях. Свойство CanSeek позволяет узнать, поддерживает ли поток произвольный
доступ. Если свойство равно True, значит, в производном классе поддерживаются
реализации методов Seek и SetLength, а также свойств Position и Length.
В
реализации метода Seek обычно используются три значения (Begin, Current и End),
входящие в удобный перечисляемый тип SeekOrigin.
В табл. 9.7
перечислены основные методы абстрактного класса Stream, смысл которых должен
сохраниться и в производных классах.
Таблица
9.7. Основные методы класса Stream
Метод/свойство |
Описание |
||
CanRead (свойство) |
Логический признак
поддержки чтения |
||
CanSeek (свойство) |
Логический признак
поддержки произвольного доступа (позиционирования) |
||
CanWrite (свойство) |
Логический признак
поддержки записи |
||
Length (свойство) |
Длина потока
в байтах |
||
Position (свойство) |
Позиция в текущем
потоке (тип Long). Свойство доступно для чтения, а в некоторых потоках
— и для записи |
||
Close |
Закрывает поток
и освобождает используемые ресурсы (например, файловые манипуляторы
операционной системы) |
||
Flush |
Записывает данные
и стирает содержимое всех буферов, используемых потоком |
||
Read(ByVal buffer()
As Byte, ByVal offset As Integer, ByVal count As Integer) |
Читает заданное
количество байтов начиная с текущей позиции с прибавлением заданного
смещения offset. Возвращает количество успешно прочитанных байтов |
||
Read Byte |
Читает отдельный
байт (почему-то в формате Integer) в текущей позиции потока. Если
текущая позиция находится в конце потока, возвращает -1 |
||
Write(ByVal
buffer() As Byte, ByVal offset As Integer, ByVal count As Integer) |
Записывает заданное
количество байтов начиная с текущей позиции с прибавлением заданного
смещения offset |
||
WriteByte(ByVal
value As Byte) |
Записывает байт
в текущую позицию потока |
||
Все классы
иерархии Stream поддерживают метод Close, освобождающий удерживаемые ресурсы
операционной системы (например, файловые манипуляторы или сетевые соединения),
поэтому практически во всех программах, работающих с потоками, рекомендуется
закрывать поток в блоке Try-Catch-Final 1у. Учтите, что вызов Close в секции
Finally требует предварительной проверки, поскольку этот метод вызывается лишь
для существующих объектов потоков, созданных успешным вызовом конструктора.
Проверка перед вызовом Close в секции Final ly выглядит примерно так:
Finally
If Not (myFileStream Is Nothing) Then myFileStream.Close()
End Try
Рассмотрите
и такую возможность, как реализация IDisposable в классах, выполняющих операции
с файлами, и закрытие всех открытых потоков методом Dispose.
Основные классы, производные от Stream, перечислены в табл. 9.8.
Таблица
9.8. Основные классы, производные от Stream
Класс |
Описание |
||
FileStream | Произвольный доступ к файлам | ||
MemoryStream | Представляет блок памяти (часто используется при работе с буферами) | ||
NetworkStream | Данные, полученные в виде потока по сетевому соединению. Принадлежит пространству имен System. Net. Sockets | ||
CryptoStream | Шифровка и расшифровка данных. Принадлежит пространству имен System. Security. Cryptography | ||
BufferedStream | «Оболочка» для поддержки буферизации в потоках, не обладающих этой возможностью (при использовании позволяет задать размер буфера). Например, автоматическая буферизация ввода используется в файловых потоках, но отсутствует в сетевых потоках. Если потребуется организовать буферизацию для сетевого потока, воспользуйтесь классом BufferedStream и методикой, описанной далее в этой главе | ||
В
.NET Framework входят классы для работы с XML, спроектированные по образцу
класса Stream. Впрочем, пространства имен XML в .NET велики и сложны, и о
них вполне можно было бы написать отдельную книгу.
Начнем с
рассмотрения команды, часто встречающейся при работе с файловыми потоками:
Dim myFileStream
As New FileStream("MyFile.txt". FileMode.OpenOrCreate, FileAccess.Write)
Как видно
из приведенного фрагмента, эта версия конструктора FileStream получает имя файла
(заданное по отношению к текущему каталогу, если не указано полное имя) и два
параметра, значения которых относятся к перечисляемым типам FileMode и FileAccess
соответственно. Таким образом, в нашем примере конструктор
Fi1eStream либо создает файл с именем MyFile.txt в текущем каталоге, либо открывает
его, если файл с таким именем уже существует. В любом случае программа
сможет записывать данные в файл. Часто встречаются и другие конструкторы класса
Fi leStream:
Допустимыми
значениями перечисляемого типа FileAccesS являются Read, Write и ReadWri te.
Основные значения перечисляемого типа Fi I eMode перечислены в табл. 9.9. Учтите,
что некоторые из них требуют особых привилегий для операций с файлами.
Таблица
9.9. Значения перечисляемого типа FileMode
Значение |
Описание |
||
Append | Открыть существующий файл (или создать несуществующий). Указатель текущей позиции перемещается в конец файла для записи. Используется совместно с FileAccess.Write | ||
Create | Создать новый файл. Внимание — существующий файл автоматически стирается! | ||
CreateNew | Создать новый файл. Отличается от Create тем, что для существующего файла инициируется исключение IOException | ||
Open | Открыть существующий файл. Если файл не существует, инициируется исключение IOException. Используется совместно с FileIOPermissionAccess.Read | ||
OpenOrCreate | Открыть или создать файл | ||
Truncate | Открыть существующий файл, удалить текущее содержимое | ||
Объекты
FHeStream также возвращаются следующими методами классов File и FHelnfo: File.Create,
File.Open, File.OpenRead, File.OpenWrite, FHeInfo.Create, FHelnfo.Open, FHelnfo.OpenRead.
Хотя файловые
потоки поддерживают произвольный доступ методом Seek, базовый класс-FileStream
ориентирован исключительно на операции с байтами, поэтому его возможности ограничиваются
простой записью байта или массива байтов методами WriteByte и Write. Приведенный
ниже фрагмент создает файл, показанный на рис. 9.2:
Option Strict On Imports System.IO
Module Modulel
Sub Main()
Dim i As Integer
Dim theBytes(255)
As Byte
For i = 0 To
255
theBytes(i)
= CByte(i)
Next
Dim myFileStream
As FileStream
Try
myFileStream
= New FileStream("C:\foo",
Fi1eMode.OpenOrCreate. FileAccess.Write)
myFlleStream.Write(theBytes,
0. 256) Finally
If Not (myFileStream Is Nothing) Then
myFileStream.Close()
End Try
DisplayAFile("C:\foo")
End Sub
End Module
Рис.
9.2. Запись двоичных данных в файл
После выполнения
этого фрагмента записанные данные можно прочитать методом Read, а также воспользоваться
методом Seek для перехода к произвольной позиции в файле. Впрочем, как это всегда
бывает при работе с неструктурированными потоками байтов, вам придется самостоятельно
преобразовать двоичные данные в более полезный формат. В результате сейчас трудно
найти более содержательный пример, чем простой вывод записанных чисел процедурой,
приведенной ниже:
Sub ReadDataBack()
Dim myFileStream
As Stream.i As Integer Try
myFileStream
= New FileStream("C:\foo",
FileMode.Open. FileAccess.Read)
For i = 0 To
255
Console.Write(myFileStream.ReadByte)
Next
Catch e As Exception
MsgBox(e.Message)
Finally
If Not (myFileStream Is Nothing) Then
myFileStream.Close()
End Try
End Sub
Метод Length
базового класса Stream всегда позволяет прочитать нужное количество байтов в
цикле независимо от структуры файла. Например, следующая процедура читает файл
по одному байту. Обнаруженные исключения просто передаются вызывающей стороне;
вероятно, в реальной программе следовало бы определить новый класс исключения:
Sub DisplayAFile(ByVal theFileName As String)
Dim theFile As FileStream
Dim i As Long
Try
theFile = New
FileStream(theFileName.
Fi1eMode.Open,Fi1eAccess.Read)
For i = 0 To (theFile.Length - 1)
' Вычесть 1. поскольку отсчет начинается с 0
Consolе.Write(theFiIe.ReadByte) Next
Catch Throw
Finally
If Not (theFile Is Nothing) Then theFile.Close()
End Try
End Sub
Если
файл имеет небольшие размеры и легко помещается в памяти, воспользуйтесь одним
вызовом Read и прочитайте весь файл в байтовый массив нужного размера. Такая
операция выполняется значительно быстрее.
Другой распространенный
вариант посимвольного чтения основан на том, что метод ReadByte в конце потока
возвращает -1. Основной цикл выглядит примерно так:
Dim i As Integer i = theFile.ReadByte
Do Until i =-1
Console.Write(i)
i = theFile.ReadByte
Loop
Чтение/запись
файла на уровне отдельных байтов используется не так уж часто; в основном это
необходимо при выполнении низкоуровневых операций. При операциях более высокого
уровня часто используется стандартный прием — неструктурированный файловый поток
передается конструктору потока, обладающего более широкими возможностями. Этот
принцип называется многоуровневой организацией потоков. Например, неструктурированный
файловый поток можно передать потоку, автоматически распознающему текст. Разные
способы многоуровневой организации потоков описаны в нескольких ближайших разделах.
Но прежде, чем переходить к этим разделам, просмотрите табл. 9.10 — в ней перечислены
основные методы и свойства базового класса FileStream. В дальнейшем мы будем
использовать эти
методы, хотя базовый файловый поток будет скрыт потоками более высоких уровней.
Таблица
9.10. Основные члены класса RleStream
Метод/свойство |
Описание |
||
Handle (свойство) |
Файловый манипулятор
операционной системы для файла, инкапсулированного в объекте FileStream.
Свойство доступно для чтения |
||
Length (свойство) |
Размер потока
в байтах. Свойство доступно для чтения |
||
Name (свойство) |
Уточненное имя,
переданное конструктору FileStream |
||
Position (свойство) |
Текущая позиция
для операций чтения или записи в потоке (нумерация позиций начинается
с нуля). Свойство доступно для чтения и записи |
||
Close |
Закрывает поток
и освобождает все связанные с ним ресурсы |
||
Flush |
Пересылает все
данные из буфера в устройство. Автоматически вызывается при вызове
Close |
||
Lock(ByVal position
As Long, ByVal length
As Long) |
Блокирует доступ
ко всему файлу или его части со стороны других процессов (нумерация
позиций начинается с нуля) |
||
Read(ByVal array()
As Byte, ByVal offset
As Integer, ByVal count
As Integer) |
Читает заданное
количество байтов в массив из файлового потока начиная
с заданной позиции |
||
ReadByte |
Читает один
байт из файла и перемещает указатель текущей позиции на один
байт вперед |
||
Seek(ByVal offset
As Long, ByVal origin
As SeekOrigin) |
Устанавливает
указатель текущей позиции в потоке в заданное положение |
||
Unlock(ByVal
position As Long, ByVal length
As Long) |
Снимает блокировку
с ранее заблокированной части файла (нумерация позиций
начинается с нуля) |
||
Write(ByVal
array() As Byte, ByVal offset
As Integer, ByVal count
As Integer) |
Записывает заданное
количество байт из массива в файловый поток начиная
с заданной позиции |
||
WriteByte |
Записывает байт
в текущую позицию файлового потока |
||
![]() |
![]() |
![]() |