Завершение работы программы обычно также происходит по инициативе пользователя и приводит к закрытию окна
Вид материала | Документы |
- Запуск программы 5 Настройка программы 5 Интерфейс формы «Печать расписания» 6 Формирование, 199.79kb.
- Руководство по установке и обновлению программа «баланс-2W», 329.37kb.
- Восстановительный подход в разрешении конфликтных и криминальных ситуаций, 50.93kb.
- Задачи проекта: Оценка уровня «эмоционального выгорания» в среде педагогов Разработка, 43.7kb.
- Сервисные функции программы рпт 76 2 Руководство пользователя 79 1Запуск программы, 660.23kb.
- Не предназначены для 100%-го удаления всего, что было привнесено в систему при установке, 1718.33kb.
- Учебно-тематический план, 40.44kb.
- Знакомство с Borland C++Builder, 178.76kb.
- Гюго В. Собрание сочинений, 1331.32kb.
- Завершение финансового года всегда сопровождается определенными трудностями. Завершение, 34.65kb.
Сохранение результатов
Возможность хранить информацию в постоянной памяти является необходимым свойством большинства программных приложений. Для этого используются несколько различных подходов:
- Файловый ввод-вывод.
- Механизм сериализации.
- Базы данных.
Далее рассмотрим, как практически организовать использование постоянной памяти с помощью файлов и сериализации. Работа с базами данных в этом пособии не рассматривается.
Работа с файлами – наиболее традиционный способ использования постоянной памяти. Для этого в С# имеется множество классов, содержащихся в пространстве имен System.IO. Классы этого пространства имен можно разбить на 2 категории:
- Классы, управляющие объектами файловой системы.
- Классы, использующие потоки.
Управление объектами файловой системы
Как правило, файловая система представляется пользователю как иерархия объектов трех видов – диски, папки и файлы. Говоря о дисках, мы имеем ввиду логические диски, представленные пользователю по именам C: D: и т.д.
Классы, предоставляющие нужные нам возможности, находятся в пространстве имен System.IO. По какой-то причине разработчики «перестарались» и предоставили нам классы с существенно пересекающимися возможностями. Поэтому в других пособиях Вы можете встретиться с альтернативными способами решения тех же задач.
Информация о логических дисках (класс DriveInfo)
С помощью статического метода GetDrives класса DriveInfo можно получить массив объектов DriveInfo, а затем узнать о каждом диске подробную информацию:
DriveInfo[] allDrives = DriveInfo.GetDrives();
foreach (DriveInfo d in allDrives)
{ Console.WriteLine("Диск {0} Тип: {0}", d.Name, d.DriveType);
if (d.IsReady == true)
{ Console.WriteLine(" Метка: {0}", d.VolumeLabel);
Console.WriteLine(" Файловая система: {0}", d.DriveFormat);
Console.WriteLine(" Доступно пользователю:{0, 15} bytes",
d.AvailableFreeSpace);
Console.WriteLine(" Свободно:{0, 15} bytes", d.TotalFreeSpace);
Console.WriteLine(" Всего:{0, 15} bytes ", d.TotalSize);
}
}
Результат работы этого фрагмента может быть следующим:
Диск C:\ Тип: Removable
Диск C:\ Тип: Fixed
Метка:
Файловая система: NTFS
Доступно пользователю: 11452694528 байт
Свободно: 11452694528 байт
Всего: 31453437952 байт
Диск D:\ Тип: Fixed
Метка: Work
Файловая система: NTFS
Доступно пользователю: 29906001920 байт
Свободно: 29906001920 байт
Всего: 62915133440 байт
Диск F:\ Тип: CDRom
В этом списке присутствуют обозначения и съемных и виртуальных дисков.
Работа с каталогами (папками)
Для решения этих задач можно использовать класс DirectoryInfo.
Для начала с помощью свойства RootDirectory класса DriveInfo получим доступ к объекту DirectoryInfo, представляющему корневой каталог некоторого диска (в примере – второго диска):
DirectoryInfo rootDir = allDrives[1].RootDirectory;
Console.WriteLine(rootDir.FullName); //выводит полное имя
Далее выведем список имен подкаталогов корневого каталога. Здесь используется метод GetDirectories:
Console.WriteLine("Подкаталоги");
foreach (DirectoryInfo di in rootDir.GetDirectories())
Console.WriteLine(" {0}",di.Name);
Аналогично с помощью метода GetFiles выведем список имен файлов (объекты FileInfo):
Console.WriteLine("Файлы");
foreach (FileInfo fi in rootDir.GetFiles())
Console.WriteLine(" {0}", fi.Name);
Часто приходится осуществлять перебор каталогов не только непосредственно внутри заданного каталога, но и на всю глубину вложенности. Для этого обычно реализуют рекурсивный алгоритм, подобный следующему:
static void TraverseDirectory(DirectoryInfo curDir, string level)
{ Console.WriteLine(level + curDir.Name);
foreach (DirectoryInfo di in curDir.GetDirectories())
TraverseDirectory(di, level + " ");
foreach (FileInfo fi in curDir.GetFiles())
Console.WriteLine(level + " " + "{0}", fi.Name);
}
Строковая переменная level помогает выводит имена файлов и каталогов с текстовыми отступами, соответствующими их уровням.
Поскольку файловая система имеет правильную древовидную организацию, каждое рекурсивное «погружение» обязательно приведет на тот уровень вложенности, где уже нет подкаталогов. В этом случае цикл foreach, осуществляющий рекурсивные вызовы будет пустым. Таким образом, все процедура обхода не окажется бесконечной. Однако применять этот прием нужно с осторожностью, поскольку на интенсивно используемом компьютере образуется чрезвычайно многоуровневая система каталогов и выполнение такого рекурсивного алгоритма приведет к исчерпанию вычислительных ресурсов (обычно такая ситуация формулируется как Stack Overflow). Потому без необходимости не применяйте этот прием для всего логического диска:
DriveInfo[] allDrives = DriveInfo.GetDrives();
DirectoryInfo rootDir = allDrives[1].RootDirectory;
Лучше определить конкретный каталог для перебора:
DirectoryInfo rootDir = new DirectoryInfo(@"D:\WORK\Крыша");
TraverseDirectory(rootDir, "");
Для получения информации о характеристиках каталогов в классе DirectoryInfo имеется несколько свойств.
Свойства только для чтения:
Exists наличие каталога.
FullName полный путь к каталогу.
Extension строка, содержащая расширение каталога.
Name имя каталога
Parent родительский каталог заданного подкаталога.
Root корневой элемент пути.
Свойства для чтения и записи:
Attributes атрибуты каталога
CreationTime время создания каталога
LastAccessTime время последнего доступа к текущему каталогу.
LastWriteTime время последней операции записи в текущий каталог.
Как видите, размер каталога Вам не предоставляется. Его придется вичислять самостоятельно рекурсивно.
Рассмотренные возможности предоставляли доступ к информации о каталогах «по чтению». Класс DirectoryInfo предоставляет и возможности «активной» работы с каталогами. Как правило, для того, чтобы выполнить какое-либо действие, связанное с каталогами, нужно сначала создать программный объект-каталог, указав его адрес:
DirectoryInfo di1 = new DirectoryInfo(@"c:\MyDir");
Это возможно как для уже физически существующего каталога, так и для вновь создаваемого.
Создание каталога.
di1.Create();
Создание подкаталога в заданном каталоге
DirectoryInfo di2 = di.CreateSubdirectory("SubDir");
Удаление каталога
di1.Delete();
Если удаляемый каталог не пуст, возникает исключение.
Перемещение (переименование) каталога
di.MoveTo(@"c:\NewTempDir");
Этот метод не позволяет перемещать каталог на другой диск (для этого придется «вручную» заняться всем содержимым каталога).
Работа с файлами
Для выполнения задач, связанных с файлами, можно использовать класс FileInfo.
Для получения списка файлов в папке используется статический метод GetFiles класса DirectoryInfo.
У методов GetDirectories и GetFiles имеется перегруженный вариант со вторым параметром, в котором можно задать шаблон (маску) интересующих папок или файлов. Например, Directory.GetFiles(@"d:\MyWork", "*.doc") вернет массив с именами Word-файлов в папке d:\MyWork.
Запись в текстовый файл |
// оператор using автоматически закрывает StreamWriter using (StreamWriter sw = new StreamWriter("TestFile.txt")) { // Добавить в файл некоторый текст sw.Write("Это "); sw.WriteLine("заголовок файла."); // В могут быть записаны объекты sw.WriteLine(DateTime.Now); } |
Чтение из текстового файла |
try { // оператор using автоматически закрывает StreamReader using (StreamReader sr = new StreamReader("TestFile.txt")) { String line; // читать и показывть строки из файла пока не конец while ((line = sr.ReadLine()) != null) Console.WriteLine(line); } } catch (Exception e) { Console.WriteLine("The file could not be read:"); Console.WriteLine(e.Message); } |
Добавление в текстовый файл |
Так же как запись в файл, но объект StreamWriter создается: FileInfo fi=new FileInfo("log.txt"); StreamWriter sw = FileInfo.AppendText(); либо StreamWriter sw = new StreamWriter("TestFile.txt",true); |
Перебор файлов каталога и определение размера файла |
DirectoryInfo di = new DirectoryInfo("c:\\"); // получить ссылку на каждый файл каталога FileInfo[] fiArr = di.GetFiles(); // Показать имена и размеры файлов Console.WriteLine("Каталог {0} содержит файлы:", di.Name); foreach (FileInfo f in fiArr) Console.WriteLine("Размер {0} - {1} байт.",f.Name,f.Length); |
Получение и изменение атрибутов файла В примере методы GetAttributes и SetAttributes применяют к файлу атрибуты Archive и Hidden (применяется техника битовых масок). |
string path = @"c:\temp\MyTest.txt"; // Создать файл, если он не существует if (!File.Exists(path)) File.Create(path); if ((File.GetAttributes(path) & FileAttributes.Hidden) == FileAttributes.Hidden) { // Показать файл File.SetAttributes(path, FileAttributes.Archive); Console.WriteLine("Файл {0} теперь виден.", path); } else { // Скрыть файл File.SetAttributes(path, File.GetAttributes(path) | FileAttributes.Hidden); Console.WriteLine("Файл {0} скрыт.", path); } |
Чтение и запись в бинарный файл |
private const string FILE_NAME = "Test.data"; public static void Main(String[] args) { // создать новый пустой файл. if (File.Exists(FILE_NAME)) { Console.WriteLine("{0} already exists!", FILE_NAME); return; } FileStream fs=new FileStream(FILE_NAME,FileMode.CreateNew); BinaryWriter w = new BinaryWriter(fs); for (int i = 0; i < 11; i++) w.Write( (int) i); w.Close(); fs.Close(); fs=new FileStream(FILE_NAME, FileMode.Open,FileAccess.Read); BinaryReader r = new BinaryReader(fs); for (int i=0; i<11; i++) Console.WriteLine(r.ReadInt32()); r.Close(); fs.Close(); } |