Компания Microsoft предоставила очень интуитивную объектную модель, охватывающую эти области, и в ходе этой главы мы покажем, как использовать классы на основе .NET для выполнения упомянутых выше задач. Для случая операций с файловой системой соответствующие классы почти все находятся в пространстве имен System.IO, в то время как операции с реестром связаны с парой классов в пространстве имен System.Win32.
Классы на основе .NET включают также ряд классов и интерфейсов в пространстве имен
System.Runtime.Serilization
, которые связаны с сериализацией, то есть процессом преобразования некоторых данных (например, содержимого документа) в поток байтов для хранения в каком либо месте. Мы не будем рассматривать эти классы в данной
главе, так как сосредоточимся на классах, которые предназначены для прямого доступа к файлам.
Отметим, что хотя безопасность влияет на все области, но особенно она важна при модификации файлов или записей реестра. Система безопасности рассматривается отдельно в главе 25. В этой главе мы будем предполагать, что имеются достаточные права доступа для выполнения всех примеров, которые модифицируют файлы или записи реестра, что обеспечивается, например, при использовании учетной записи с полномочиями администратора.
Управление файловой системой
Классы, которые используются для просмотра файловой системы и выполнения таких операций, как перемещение, копирование и удаление файлов, показаны на следующей диаграмме. Пространство имен каждого класса показано в скобках под именем каждого класса на диаграмме:
Назначение этих классов следующее:
□
System.MarshalByRefObject
— класс базового объекта для классов .NET, которые являются удаленными. Допускает маршализацию данных между прикладными доменами.
□
FileSystemInfo
— базовый класс, который представляет любой объект файловой системы.
□
FileInfo
и
File
— представляют файл в файловой системе.
□
DirectoryInfo
и
Directory
— представляют папку в файловой системе.
□
Path
— содержит статические члены, которые можно использовать для манипуляций именами путей доступа.
Отметим, что в Windows объекты, которые содержат файлы и используются для организации файловой системы, называются папками. Например, в пути доступа
C:\My Documents\ReadMe.txt
файлом является
ReadMe.txt
, а
My Documents
— папкой. Папка (folder) является специфическим для Windows терминам: практически во всех других операционных системах вместо папки используется термин каталог (directory). В соответствии с желанием Microsoft, чтобы .NET была максимально независимой от операционной системы, соответствующие базовые классы .NET называются
Directory
и
DirectoryInfo
. Однако в связи с возможной путаницей с каталогами LDAP (обсуждаемыми в главе 15), и в связи с тем, что эта книга посвящена Windows, здесь используется термин папка.
Классы .NET, представляющие файлы и папки
Из приведенного выше списка можно видеть, что существуют два класса, используемых для представления папки, и два класса для файла. Какой из этих классов будет наиболее подходящим, зависит в большой степени от того, сколько раз необходимо получать доступ к папке или файлу:
□
Directory
и
File
содержат только статические методы и никогда не создают экземпляров. Эти классы применяются с помощью предоставления пути доступа к соответствующему объекту файловой системы, когда вызывается метод-член. Если нужно выполнить только одну операцию на папке или файле, то эти классы более эффективны, так как не требуют создания экземпляра класса .NET.
□
DirectoryInfo
и
FileInfo
реализуют приблизительно те же открытые методы, что и
Directory
и
File
,
а также некоторые открытые свойства и конструкторы, но они имеют состояние и члены этих классов не являются статическими. На самом деле необходимо создать экземпляры этих классов, и при этом каждый экземпляр ассоциируется с определенной папкой или файлом. Это означает, что эти классы являются более эффективными, если выполняется несколько операций с помощью одного и того же объекта, так как они будут считывать аутентификационные и другие данные при создании соответствующего объекта файловой системы, а затем им не понадобиться больше считывать эту информацию, независимо от того, сколько методов вы будете вызывать на каждом объекте (экземпляре класса). Для сравнения, соответствующим классам без состояния понадобиться снова проверять данные файла или папки для каждого вызываемого метода.
В этом разделе мы будем в основном использовать классы
FileInfo
и
DirectoryInfo
, но оказывается, что многие (но не все) вызываемые методы реализуются также классами
File
и
Directory
(хотя в этих случаях эти методы требуют дополнительный параметр, имя пути доступа объекта файловой системы и пара методов имеют немного отличные имена). Например:
FileInfo MyFile = new FileInfo(@"C:\Program Files\My Program\ReadMe.txt");
Первый фрагмент кода будет выполняться немного дольше, так как он требует создания экземпляра объекта
FileInfo
—
MyFile
, но он оставляет
MyFile
готовым для выполнения дальнейших действий на том же файле.
Для создания экземпляра класса
FileInfo
или
DirectoryInfo
в конструктор передается строка, содержащая путь доступа к соответствующей файловой системе. Мы только что проиллюстрировали процесс для файла. Для папки код выглядит аналогично:
DirectoryInfo MyFolder = new DirectoryInfo(@"C:\Program Files");
Если путь доступа представляет объект, который не существует, то исключение будет порождено не во время создания, а в тот момент, когда будет вызван метод, которому потребовался объект соответствующей файловой системы. Можно определить существует ли объект и имеет ли соответствующий тип, проверяя свойство Exists, которое реализовано для обоих этих классов:
FileInfo Test = new FileInfo(@"C:\Windows");
Console.WriteLine(Test.Exists.ToString);
Console.WriteLine(Test.CreationTime.ToString);
Отметим, что для того, чтобы это свойство возвращало
true
, соответствующий объект файловой системы должен быть соответствующего типа. Другими словами, если создается экземпляр объекта
FileInfo
, содержащий путь доступа папки или, если создается объект
DirectoryInfo
, задающий путь доступа файла,
Exists
будет иметь значение
false
. С другой стороны, большинство свойств и методов этих объектов будут возвращать значение, если вообще это возможно. Но они не обязательно порождают исключение из-за того, что был вызван неправильный тип объекта, а только в том случае, если требовалось выполнить что-то реально невозможное. Например, приведенный выше фрагмент кода сначала выведет
false
(так как
C:\Windows
является папкой), но затем все равно правильно покажет время создания папки, так как в папке имеется эта информация. С другой стороны, если затем попробовать открыть папку, как если бы это был файл, с помощью метода