Пространства имен
В одной из первых статей мы кратко обсудили пространства имен. Вы, вероятно, узнаете ключевое слово, потому что оно находится в большинстве файлов, содержащих код C#, обычно почти в верхней части. Пространство имен-это, по сути, способ группировки набора типов, например классов, в собственном именованном пространстве. При создании нового проекта Visual Studio также создает пространство имен по умолчанию, в которое помещается первый файл (по крайней мере, это верно для типа проекта консольного приложения). Это может выглядеть так:
В этом случае пространство имен «MyProject» теперь является частью приложения и при использовании его классов вне его, вам придется использовать префикс ими класса с именем пространства имен. Вы видите то же самое, когда хотите использовать что-то скрытое глубоко в .NET framework, например:
В этом случае, мы используем ReadAllText() метод найденный в файле класса, который существует в системе .ИО в пространстве именна сайте. Конечно, было бы утомительно писать такое длинное имя каждый раз, когда вы хотите использовать класс из пространства имен, поэтому C# позволяет «импортировать» все пространство имен в область вашего файла с помощью с помощью оператора. Опять же, вы, возможно, уже знаете их, потому что вы обычно можете найти их в верхней части ваших файлов C#. В приведенном выше примере, если нам потребуется класс File более одного раза, имеет смысл импортировать систему. Пространство имен IO с помощью оператора using, как это сделано здсь:
Для чего нужны пространства имен?
Если вы только начали программировать, вы можете задаться вопросом, для чего нам нужны пространства имен. Почему бы просто не поместить все ваши классы в те же пространства имен, чтобы они всегда были доступны? У вас есть действительный пункт, но только если ваш проект очень мал. Как только вы начинаете добавлять все больше и больше классов, имеет смысл разделить их на пространства имен. Это просто упрощает поиск кода, особенно если файлы размещаются в соответствующих папках . фактически, если добавить папку в проект, а затем добавить в него класс, Visual Studio автоматически поместит его в соответствующее пространство имен. Таким образом, если создать папку в MyProject с именем MyFolder, классы, добавленные в эту папку, по умолчанию будут помещены в пространство имен с именем MyProject.MyFolder.
Отличный пример того, зачем нужны пространства имен это сам .NET framework. Только подумайте, если бы все классы в нем просто плавали в глобальном пространстве имен — это был бы беспорядок! Вместо этого, они организовали красиво, с System в качестве корневого пространства имен для большинства классов, а затем суб-пространства имен, например System.IO для материалов ввода/вывода, в System.Net для поиска в сети материалов и System.Net.Mail для вещей, связанных с почтой.
Конфликт имен в Пространстве имен
Как уже упоминалось, пространства имен также предназначены для инкапсуляции типов (обычно классов), чтобы они могли существовать в собственном домене. Это также означает, что вы можете создавать классы с тем же именем, что и в других частях проекта или даже в .NET framework. Например, вы можете решить, что вам нужен собственный класс файлов File. Как мы видели в предыдущих примерах, такой класс уже существует в пространстве имен System.IO, но вы можете создать его в своем собственном пространстве имен, например:
Теперь, когда вы хотите использовать его в своем проекте, например, в своей программе на С# метод Main (если вы работаете с Консольным приложением, как я), Вы можете написать полное имя:
Но вы также можете импортировать пространство имен, как и любое другое пространство имен (встроенное или определяемое пользователем), благодаря оператору using. Вот более полный пример:
Пока все хорошо! Однако, если вы хотите использовать файл класса из пространства имен System.IO? Ну, вот где начинаются проблемы. Потому что если вы импортируете это пространство имен, а также, с помощью оператора using, компилятор больше не знает, какой файловый класс вы имеете в виду — наш собственный или один из System.IO. Это можно решить, импортировав одно из пространств имен (в идеале то, из которого вы используете большинство типов), а затем полностью указав имя другого, как в этом примере:
Но это немного громоздко вводить каждый раз, особенно если ваш класс еще глубже вложен в пространства имен, например MyProject.FileStuff.IO.File. К счастью, в C# есть решение для этого.
Использование директивы Alias
Чтобы сократить имя пространства имен, можно импортировать пространство имен под другим именем с помощью директивы Alias. Обратите внимание, как я это делаю в следующем примере:
Волшебство происходит в третьей строке, где я обращаюсь к MyProject.IO и даю ему более короткое имя (MyIO), которые затем может быть использовано, когда мы хотим получить доступ к типам из него. На данный момент мы не экономим много нажатий клавиш, но опять же вы должны представить себе еще более длинные имена и уровни пространств имен, и поверьте мне, они могут быть довольно длинными и вложенными.
Резюме
Пространства имен дают возможность инкапсулировать типы в «именованные пространства», что позволяет получить лучшую структуру в коде, а также иметь несколько классов с одинаковыми именами, если они существуют в отдельных пространствах имен.
C#: Файлы и как с ними работать
Сегодня я решил рассказать тем, кто еще только начинает изучать язык программирования C# о механизме работы с файлами.
Работа с файлами в C# возможна благодаря очень мощному неймспейсу System.IO. Мы рассмотрим две основных возможности данной библиотеки — работа с файлами и работа с текстовыми файлами. Да да, разработчики уделили отдельное внимание методам для работы с текстовыми файлами — за что им стоит сказать огромное спасибо. Ведь это значительно облегчает процесс разработки. Начнем рассматривать методы работы с файлами.
Работа с текстовыми файлами в C#
Для работы с текстовыми файлами применяются два класса StreamReader и StreamWriter. По названию классов видно, что первый используется для работы с файлами в режиме чтения, второй для работы в режиме записи. Они интуитивно понятны, так как все их методы явно отражают действия. Приведем пример чтения по строкам:
Объект sr так же имеет методы ReadToEnd, ReadBlock и другие. Названия этих методов говорят сами за себя.
Пример записи в файл:
Так же стоит отметить, что оба класса реализуют интерфейс IDisposable. А это означает, что предпочтительней использовать конструкцию using.
Более того в библиотеке IO есть несколько предопределенных наиболее часто используемых операций. Нет смысла подробно описывать данные функции, нужно просто запомнить их
Чтение всего текстового файла в переменную
Чтение всего текстового файла построчно в массив
Работа с бинарными файлами в C#
C# позволяет очень гибко работать с бинарными файлами. В связи с этим вариантов написать один и тот же код очень много. Поэтому я просто приведу пример базовой работы с файлами на примере копирования файла с использованием FileStream.
Примечание: Параметры FileMode, FileAccess и FileShare играют очень важную. Они отвечают за флаги, которые будут проставлены файлу, пока он занят вашей программой. Именно они могут запретить/разрешить доступ к файлу сторонним программам, либо «попросить» разрешение на чтение уже занятого файла.
Пространство имен System.IO
Пространство имен System.IO в .NET — это область библиотек базовых классов, посвященная службам файлового ввода-вывода, а также ввода-вывода из памяти. Подобно любому пространству имен, в System.IO определен набор классов, интерфейсов, перечислений, структур и делегатов, большинство из которых находятся в mscorlib.dll. В дополнение к типам, содерясащимся внутри mscorlib.dll, в сборке System.dll определены дополнительные члены пространства имен System.IO.
Многие типы из пространства имен System.IO сосредоточены на программных манипуляциях физическими каталогами и файлами. Дополнительные типы предоставляют поддержку чтения и записи данных в строковые буферы, а также области памяти.
Эти классы позволяют сохранять и извлекать элементарные типы данных (целочисленные, булевские, строковые и т.п.) в двоичном виде.
Этот класс предоставляет временное хранилище для потока байтов, которые могут затем быть перенесены в постоянные хранилища
Эти классы используются для манипуляций структурой каталогов машины. Тип Directory представляет функциональность, используя статические члены. Тип DirectoryInfo обеспечивает аналогичную функциональность через действительную объектную ссылку.
Этот класс предоставляет детальную информацию относительно дисковых устройств, используемых данной машиной
Этот класс обеспечивает произвольный доступ к файлу (т.е. возможности поиска) с данными, представленными в виде потока байт.
Этот класс позволяет отслеживать модификации внешних файлов в определенном каталоге.
Этот класс обеспечивает произвольный доступ к данным, хранящимся в памяти, а не в физическом файле
Этот класс выполняет операции над типами System.String, содержащими информацию о пути к файлу или каталогу в независимой от платформы манере
Эти классы используются для хранения (и извлечения) текстовой информации из файла. Эти классы не поддерживают произвольного доступа к файлу
Подобно классам StreamWriter/StreamReader, эти классы также работают с текстовой информацией. Однако лежащим в основе хранилищем является строковый буфер, а не физический файл
Файловых операций (Directory, DirectoryInfo, File, FileInfo)
Данные классы предназначены для работы с папками и файлами:
Directory и DirectoryInfo – для работы с папками, а File и FileInfo – с файлами. Отличие этих классов в том, что классы Directory и File — статические, а DirectoryInfo и FileInfo позволяют создавать объекты. Назначение же и тех и других одинаковое.
Класс Path работа с путями
Path это статический класс.NET, облегчающий работу с путями.
| Название метода | Назначение |
|---|---|
| Path.ChangeExtension | Позволяет изменить расширение файла в пути. |
| Path.Combine | Позволяет объединить две части пути папке и имя файла. |
| Path.GetDirectoryName | Вычленяет из полного пути путь к папке (безоконечного разделителя \) |
| Path.GetExtension | Вычленяет из полного пути расширение файла(с лидирующей точкой) |
| Path.GetFileName | Вычленяет из полного пути имя файла с расширением. |
| Path.GetFileNameWithoutExtension | Вычленяет из полного пути имя файла без расширения. |
| Path.GetFullPath | Возвращает полный путь по относительному. |
| Path.GetInvalidFileNameChars | Возвращает массив символов, которые не могут быть использованы в имени файла. |
| Path.GetInvalidPathChars | Возвращает массив символов, которые не могут быть использованы в пути. |
| Path.GetInvalidFileNameChars | Возвращает массив символов, которые не могут быть использованы в имени файла. |
| Path.GetPathRoot | Возвращает корень (диск, с оконечным разделителем /) данного пути. |
| Path.GetRandomFileName | Генерирует корректное случайное имя файла (с расширением). |
| Path.GetTempFileName | Генерирует уникальное имя файла во временной папке и возвращает полный путь к нему. |
| Path.GetTempPath | Возвращает полный путь к временной папке. |
| Path.HasExtension | Возвращает булевое значение – есть ли расширение у файла (true) или нет (false). |
| Path.IsPathRooted | Возвращает булевое значение – абсолютный ли путь (true) или нет (false). |
Класс Drivelnfo
Класс Drivelnfo позволяет получить информацию о дисковом устройстве компьютера. Интерес представляют относительно немного частей этой информации — обычно класс Drivelnfo применяется лишь для получения общего объема использованного и свободного пространства.
| Член | Описание |
|---|---|
| TotalSize | Получает общий объем устройства в байтах. Это включает сумму выделенного и свободного места |
| TotalFreeSpace | Получает общий объем свободного пространства в байтах |
| AvailableFreeSpace | Получает общий объем доступного пространства в байтах. Доступное пространство может быть меньше, чем общее свободное пространство, если для вас установлена квота свободного дискового пространства, которое может использовать процесс ASP .NET |
| DriveFormat | Возвращает имя файловой системы, используемой на устройстве (такое как NTFS или FAT32) |
| DriveType | Возвращает значение из перечисления DriveType, которое указывает, является ли диск фиксированным, сетевым, CD-ROM, RAM или съемным диском. (Если определить тип диска не удалось, возвращает Unknown.) |
| IsReady | Возвращает признак готовности устройства для операций чтения или записи. |
| Name | Возвращает букву имени диска (наподобие С: или E: |
| VolumeLabel | Получает или устанавливает описательную метку тома устройства. Если это устройство формата NTFS, метка может содержать до 32 символов. Если метка не установлена, свойство вернет null |
| RootDirectory | Возвращает рбъект Directorylnfo, описывающий корневой каталог дискового устройства |
| GetDrives() | Возвращает массив объектов DriveiInfо, представляющий все логические устройства данного компьютера |
FileStream Класс (низка уровневый)
Класс FileStream представляет собой поток файла. Он позволяет производить операции чтения и записи из файлов (как синхронные, так и асинхронные). Данный класс поддерживает метод Seek, что позволяет перемещать текущее положение курсора в файле.
Пример использования данного класса:
Особого внимания заслуживает конструктор FileStream:
Первым параметром передается путь к файлу (с именем и расширением) в виде переменной или литерала String.
Второй параметр данного конструктора – переменная типа FileMode (перечисление). Он описывает, каким образом файл должен быть открыт операционной системой.
| Перечислитель | Описание |
|---|---|
| FileMode.Append | Открывает файл, если он существует, и перемещает курсор в конец файл.Если файл не существует – создает новый файл. FileMode.Append можно использовать только вместе с FileAccess.Write. |
| FileMode.Create | Создает новый файл, если файл уже существует, то он будет переписан. |
| FileMode.CreateNew | Создает новый файл, если файл уже существует, то будет вызвано исключение IOException. |
| FileMode.Open | Открывает существующий файл, если файла не существует,то будет вызвано исключение FileNotFoundException. |
| FileMode.OpenOrCreate | Открывает существующий файл, если файла не существует,то будет создан новый файл. |
| FileMode.Truncate | Открывает существующий файл и усекает его размер до нуля. |
Третий параметр переменная типа FileAccess Он описывает, каким образом осуществляется доступ к файлу.
| Перечислитель | Описание |
|---|---|
| FileAccess.Write | только на запись |
| FileAccess.Read | только на чтение |
| FileAccess.ReadWrite | запись и чтение |
Последний параметр – переменная типа FileShare этот параметр позволяет управлять доступом, который другие объекты FileStream могут осуществлять к этому файлу.
| Перечислитель | Описание |
|---|---|
| FileShare.Delete | Разрешает удаление файла. |
| FileShare.Inheritable | Разрешает наследование дескриптора файла дочерними процессами. В Win32 непосредственная поддержка этого свойства не обеспечена. |
| FileShare.None | Отклоняет совместное использование текущего файла. Любой запрос на открытие файла не выполняется до тех пор, пока файл не будет закрыт. |
| FileShare.Read | Разрешает последующее открытие файла для чтения. |
| FileShare.ReadWrite | Разрешает последующее открытие файла для чтения или записи. |
| FileShare.Write | Разрешает последующее открытие файла для записи. |
Класса StreamWriter и StreamReader для файловых операций
Не всегда удобно работать с байтовыми массивами. И для этого существуют классы-обертки.
Такими классами обертками для работы с символами и строками могут служить классы System.IO.StreamReader и System.IO.StreamWriter.
При работе с этими классами стоит обратить внимание на следующие моменты. У объектов типа StreamWriter есть булевое свойство AutoFlush, установив которое в true можно не вызывать каждый раз метод Flush() после записи очередного блока данных в поток.
У объектов типа StreamReader стоит обратить внимание на булевое свойство EndOfStream, которое показывает, не достигли ли мы конца потока. Также у них определено несколько методов для чтения:
класса BinaryWriter и BinaryReader для файловых операций
Данные классы предназначены для записи простых типов данных в поток в виде двоичных значений, а также строк в определенной кодировке. Они выступают в виде обертки для других, базовых потоков.
Объекты класса BinaryWriter имеют всего один метод для записи (Write), который имеет несколько перегруженных вариантов, принимающих объекты различных типов данных.
Объекты же класса BinaryReader имеют несколько методов, которые предназначены для чтения различных типов данных.
При их использовании необходимо обратить внимание на то, что данные с помощью BinaryReader’a необходимо читать в том же порядке, в котором они были записаны BinaryWriter’ом.