HTML-приложения: работа с файлами, папками и дисками (ч.1)
В предыдущей статье цикла, посвящённого HTML-приложениям Internet Explorer (HTA), мы рассматривали возможности файлового ввода-вывода и учились читать текстовую информацию из файлов и записывать её в них. Теперь мы можем наделить HTML-приложения возможностью работы с документами, хранящимися в файлах.
Однако возможности WSH по работе с файлами этим не исчерпываются. Различные объекты, реализуемые этой программой, позволяют нам также:
- получать сведения о файлах (имя, размер, даты создания, последнего изменения и последнего открытия и др.);
- получать сведения о папках (имя, размер, даты создания, последнего изменения и последнего открытия, является ли папка корневой и др.);
- получать сведения о дисках (тип, общий объём, объём свободного пространства и др.);
- создавать, копировать, перемещать, переименовывать и удалять файлы и папки;
- выполнять вспомогательные задачи (получать путь к папке, в которую вложена данная папка, получать уникальное имя временного файла и др.).
Данная статья целиком посвящена рассмотрению всех перечисленных выше возможностей WSH и соответствующих им объектов.
Примечание:
Перед чтением этой статьи настоятельно рекомендуется ознакомиться с предыдущими статьями цикла, посвящённого HTML-приложениям Internet Explorer.
Если средства файлового ввода-ввода, рассмотренные нами в предыдущей статье цикла, поддерживали работу только с текстовыми файлами, то инструменты, что мы рассмотрим в этой статье, позволяют работать с файлами любого формата.
1. Получение доступа к средствам файлового ввода-вывода WSH
Как получить доступ к средствами для работы с файловой системой WSH, описывалось в предыдущей статье цикла. Для этого достаточно создать экземпляр объекта Scripting.FileSystemObject - ключевого объекта WSH. Поскольку этот объект реализуется компонентом ActiveX (то есть является внешним объектом), для его создания используется конструктор ActiveXObject, а в качестве единственного его параметра указывается строка с именем объекта, экземпляр которого нужно создать.
var oFSO = new ActiveXObject("Scripting.FileSystemObject");
2. Работа с файлами
Начнём с рассмотрения принципов работы с файлами, так как именно с этими объектами файловой системы мы будем чаще всего иметь дело.
2.1. Получение нужного файла
Первое, что нам нужно сделать, - получить файл, с которым мы собираемся работать. Забегая вперёд, скажем, что файл в WSH представляется экземпляром особого объекта; с помощью его свойств мы сможем получить сведения о нём, а с помощью методов - управлять им.
Для получения файла, так сказать, напрямую мы используем метод GetFile объекта FileSystemObject. Вот формат его вызова:
<экземпляр объекта FileSystemObject>.GetFile(
<путь к файлу>
);
Первым параметром этому методу передаётся путь к открываемому файлу. Он должен быть указан в виде строки.
Примечание:
Если мы зададим путь к несуществующему файлу, то при выполнении веб-сценария получим сообщение об ошибке. Поэтому лучше перед получением файла проверить, действительно ли он существует на диске (об этом - позже).
Кроме того, если мы укажем путь к файлу, расположенному на диске, который в это время ещё не готов к работе (например, привод компакт-дисков, в который не вставлен диск), то также получим ошибку. Поэтому перед доступом к такому диску следует проверить, готов ли он (как это сделать, будет описано далее).
Метод GetFile возвращает экземпляр объекта File, представляющий полученный файл. Да-да, File - тот самый объект, которым представляется файл и который упоминался в начале этого параграфа.
var oF = oFSO.GetFile("c:\\Work\\testdata.txt");
Здесь мы получили в виде экземпляра объекта File файл testdata.txt, расположенный в папке Work диска C:\.
При указании путей к файлам следует иметь в виду следующее. Для разделения имён папок и файла в путях применяется символ обратного слеша (\). Этот же символ применяется для указания специальных символов (литералов) в строковых значениях JavaScript; например, литерал \" обозначает символ двойной кавычки, который нельзя просто так вставить в строку. Так вот, чтобы поместить в строку именно символ обратного слеша, следует использовать литерал \\ (что мы и сделали в предыдущем примере). Запомним это на будущее.
2.2. Получение сведений о файле
Получив файл, мы сможем извлечь различные сведения о нём. Это выполняется с помощью набора свойств объекта File, которые мы сейчас рассмотрим. Почти все эти свойства доступны только для чтения; если какие-то свойство доступно также и для записи, мы специально это укажем.
Свойство Name хранит строку с именем файла. Отметим, что это именно имя файла с расширением, а не полный путь. Данное свойство доступно также и для записи, что позволяет нам переименовывать файлы.
var sFileName = oF.Name;
Свойство ShortName возвращает строку с сокращённым до размеров 8.3 именем файла. И в этом случае возвращается именно имя файла с расширением, а не полный путь. Свойство Path возвращает строку с полным путём к данному файлу. Свойство ShortPath возвращает строку с полным путём к данному файлу, имена папок и файла в котором сокращены до размеров 8.3.
var sPath = oF.Path;
Свойство ParentFolder возвращает строку с полным путём к папке, в которой находится файл. При этом путь возвращается без конечного символа обратного слеша.
var sFolder = oF.ParentFolder;
Данное выражение поместит в переменную sFolder строку "c:\\Work" - путь к папке, в которой находится данный файл. Отметим, что этот путь не имеет конечного символа обратного слеша.
Свойство Drive возвращает строку с наименованием диска, на котором хранится файл. Это наименование имеет вид буквы, отведённой системой данному приводу, за которой следует символ двоеточия. Никаких обратных слешей возвращённая строка не содержит.
var sDrive = oF.Drive;
Выполнив это выражение, мы получим в переменной в переменной sDrive окажется строка "c:" - наименование диска, где хранится файл.
Свойство Type возвращает строку с обозначением типа файла, под которым он зарегистрирован в системе. Насколько эти сведения будут нам полезны - непонятно...
var sType = oF.Type;
Это выражение поместит в переменную sType строку "Текстовый документ" - именно под таким обозначением зарегистрирован в системе текстовый тип файлов (расширение txt).
Свойство Size возвращает размер файла в байтах в виде целого числа.
iSize = oF.Size;
Три перечисленных ниже свойства позволяют узнать различные значения даты и времени, связанными с файлом. Все они возвращают экземпляры объекта Date.
- DateCreated - возвращает дату создания файла.
- DateLastModified - возвращает дату последнего изменения файла.
- DateLastAccessed - возвращает дату последнего доступа к файлу.
var dCreated = oF.DateCreated;
Свойство Attributes хранит целое число, обозначающее атрибуты файла. Это целое число представляет собой сумму чисел, каждое из которых указывает на какой-либо установленный атрибут; все эти числа перечислены ниже.
- 0 - ни один из атрибутов не установлен.
- 1 - установлен атрибут "только для чтения".
- 2 - установлен атрибут "скрытый".
- 4 - установлен атрибут "системный".
- 8 - это не файл, а метка диска.
- 16 - это не файл, а папка.
- 32 - установлен атрибут "архивный".
- 1024 - файл представляет собой ярлык или жёсткую ссылку NTFS.
- 2048 - это сжатый файл.
Так, если свойство Attributes хранит число 37, то у файла установлены атрибуты "только для чтения", "системный" и "архивный".
if (oF.Attributes & 4) {
//Файл является системным
}
Обратим внимание, как мы проверяем, установлен ли у файла какой-либо атрибут. Мы выполняем логическое умножение (операцию И) значения свойства Attributes и числа, обозначающего нужный нам атрибут в установленном состоянии (см. список выше). Если в результате мы получим 1, значит, атрибут установлен, если 0 - сброшен. (Будучи использованным в качестве условия, число 1 будет преобразовано в значение true, а число 0 - в false.) Так, логически умножив значение свойства Attributes на 4, мы проверим, установлен ли у файла атрибут "системный".
if (oF.Attributes & 1024) {
//Файл является ярлыком или жёсткой ссылкой NTFS
}
Свойство Attributes доступно не только для чтения, но и для записи. Записав в него новое значение, мы можем изменить атрибуты файла.
if (oF.Attributes & 2)
oF.Attributes = oF.Attributes - 2;
Это выражение проверяет, установлен ли у файла атрибут "скрытый", и, если установлен, сбрасывает его.
Поскольку значение свойства Attributes представляет собой сумму чисел, указывающих на установленные атрибуты (см. список выше), то, чтобы сбросить нужный нам атрибут, нам достаточно вычесть из значения этого свойства число, обозначающее данный атрибут в установленном состоянии. Так, в предыдущем примере, чтобы сбросить у файла атрибут "скрытый", мы вычли из значения свойства Attributes число 2. Аналогично, чтобы установить какой-либо атрибут, мы прибавим обозначающее его число к значению свойства Attributes.
if (!(oF.Attributes & 32))
oF.Attributes = oF.Attributes + 32;
Это выражение проверяет, сброшен ли у файла атрибут "архивный", и, если сброшен, устанавливает его.
Примечание:
Указанным выше способом мы сможем установить или сбросить только атрибуты "только для чтения", "скрытый", "системный" и "архивный". Превратить файл в папку или сжатый файл в несжатый мы не сможем - при попытке сделать это возникнет сообщение об ошибке.
Кроме того, мы можем получить версию исполняемого файла. Для этого предназначен метод GetFileVersion объекта FileSystemObject. В качестве единственного параметра он принимает строку с полным путём к файлу и возвращает строку с номером его версии или пустую строку, если файл не содержит информации о его версии (например, если это не исполняемый файл).
var sVersion = oFSO.GetFileVersion("c:\\Work\\testfile.exe");
Получаем в переменной sVersion номер версии файла testfile.exe.
var sVersion = oFSO.GetFileVersion("c:\\Work\\testfile.txt");
Получаем в переменной sVersion пустую строку, так как текстовые файлы не содержат информации о версии.
var sVersion = oFSO.GetFileVersion(oF.Path);
Чтобы не указывать путь к полученному ранее файлу дважды, мы можем извлечь его из свойства Path. (Впрочем, файл oF - текстовый, а текстовые файлы не содержат версии... Но ведь это только пример.)
2.3. Копирование, перемещение, переименование и удаление полученного ранее файла
Теперь рассмотрим, как выполняется копирование, перемещение, переименование и удаление файла, полученного ранее с помощью метода GetFile объекта FileSystemObject.
Для копирования файла применяется метод Copy объекта File. Формат его вызова таков:
<файл>.Copy(
<путь к файлу назначения>[,
<перезаписывать ли файл, если он уже существует>]
);
Первый параметр задаёт полный путь к файлу назначения, который будет получен в результате копирования, в виде строки. Указать просто путь к папке назначения мы в этом случае не можем.
Примечание:
Если мы зададим путь к файлу назначения, содержащий несуществующие папки, то при выполнении Web-сценария получим сообщение об ошибке.
Второй, необязательный, параметр позволяет указать, что веб-сценарий будет делать, если файл назначения, путь которого мы указали первым параметром, уже существует на диске. Значение true указывает перезаписать такой файл, а значение false - не перезаписывать. Значение по умолчанию - true (то есть файл будет перезаписан).
Примечание:
Если файл назначения уже существует, и мы указали, чтобы он не перезаписывался, то при выполнении веб-сценария возникнет ошибка.
Метод Copy не возвращает результата.
oF.Copy("c:\\Work\\Temp\\testfile.txt");
Копируем полученный ранее файл testfile.txt в папку Work\Temp диска C.
oF.Copy("c:\\Work\\Temp\\" + oF.Name);
Чтобы в пути к файлу назначения самим не указывать собственно имя файла, мы можем поступить так - взять это имя из свойства Name.
oF.Copy("c:\\Work\\testfile2.txt");
Создаём копию файла testfile.txt под именем testfile2.txt в той же папке Work.
Для перемещения файла в другую папку используется метод Move объекта File. Единственный параметр этого метода задаёт путь к файлу назначения, который будет получен в результате перемещения, в виде строки. Результата этот метод не возвращает.
Примечание:
Если мы зададим путь к файлу назначения, содержащий несуществующие папки, то при выполнении веб-сценария получим сообщение об ошибке. То же самое случится, если файл назначения уже существует.
oF.Move("c:\\Work\\Temp\\testfile.txt");
Перемещаем полученный ранее файл testfile.txt в папку Work\Temp диска C.
oF.Move("c:\\Work\\testfile2.txt");
Перемещаем файл testfile.txt в ту же папку Work, но под именем testfile2.txt. Фактически мы выполняем переименование данного файла.
Хотя переименование удобнее выполнять, присвоив новое имя файла уже знакомому нам свойству Name объекта File (см. параграф 2.2).
Примечание:
Если мы зададим имя файла, который уже существует, то при выполнении веб-сценария получим сообщение об ошибке.
oF.Name = "testfile2.txt";
Для удаления файла применяется метод Delete объекта File. Формат его вызова таков:
<файл>.Delete(
[<удалить ли файл с установленным атрибутом "только для чтения">]
);
Единственный, да и тот необязательный, параметр указывает, что делать в случае, если удаляемый файл имеет установленный атрибут "только для чтения". Значение true указывает, что такой файл всё равно следует удалить, а значение false - не делать этого. Значение по умолчанию - false (файлы с установленным атрибутом "только для чтения" удаляться не будут).
Метод Delete не возвращает результата.
Примечание:
При вызове метода Delete файл будет удалён безвозвратно, без помещения в системную Корзину. При попытке удаления несуществующего файла возникнет ошибка.
oF.Delete();
2.4. Открытие полученного ранее файла
Ещё мы можем открыть полученный ранее вызовом метода GetFile объекта FileSystemObject файл, чтобы прочитать его содержимое или записать в него новое. При этом файл обязательно должен быть текстовым - работа с двоичными файлами не поддерживается - об этом уже говорилось в предыдущей статье цикла.
Открыть файл можно вызовом метода OpenAsTextStream объекта File. Вот формат его вызова:
<файл>.OpenAsTextStream(
<режим открытия>[,
<кодировка файла>]
);
Первым параметром указывается режим открытия файла. Значение 1 указывает открыть файл для чтения, значение 2 - для записи, а значение 8 - для дозаписи.
Примечание:
В документации по WSH на Web-сайте MSDN сказано, что первый параметр метода OpenAsTextStream является необязательным, но не указано его значение по умолчанию. Поэтому автор рекомендует всегда указывать первый параметр.
Второй, необязательный, параметр указывает кодировку, в которой будет прочитано содержимое открываемого файла. Отметим, что это кодировка, в которой мы будем читать содержимое файла, а не кодировка, в которой оно реально сохранено. Числовое значение 0 задаёт кодировку ASCII, значение -1 - кодировку Unicode, а значение -2 - системную кодировку по умолчанию. Значение по умолчанию - 0 (то есть указывается кодировка ASCII).
Метод OpenAsTextStream возвращает экземпляр объекта TextStream. Подробнее об этом объекте и вообще о чтении из файлов и записи в них читайте в предыдущей статье цикла.
Примечание:
Разумеется, для открытия файла мы также можем использовать метод OpenTextFile объекта FileSystemObject, описанный в предыдущей статье цикла.
2.5. Копирование, перемещение и удаление произвольного файла или файлов
Ранее мы узнали, как можно скопировать, переместить и удалить файл, полученный вызовом метода GetFile объекта FileSystemObject. Однако в этом случае, перед тем как собственно скопировать, переместить или удалить файл, нам следует его получить. То есть выполнить операцию, которая во многих случаев будет лишней...
Поэтому, если нам нужно только скопировать, переместить или удалить файл, не выполняя больше никаких манипуляций с ним, или выполнить эти действия сразу над несколькими файлами, мы можем воспользоваться способами, описанными в этом параграфе.
Так, скопировать произвольный файл мы можем, вызвав метод CopyFile объекта FileSystemObject в таком формате:
<экземпляр объекта FileSystemObject>.CopyFile(
<путь к копируемому файлу>,
<путь к файлу или папке назначения>[,
<перезаписывать ли файл, если он уже существует>]
);
Первый параметр задаёт полный путь к копируемому файлу в виде строки. В имени собственно файла допускается использовать символы-маски * и ?, так что мы можем скопировать сразу несколько файлов, удовлетворяющих определённому критерию.
Второй параметр задаёт либо путь к файлу назначения, либо путь к папке назначения в виде строки. Правило здесь очень простое: если значение второго параметра заканчивается символом обратного слеша (\) или если путь к копируемому файлу (значение первого параметра) содержит символы-маски, то предполагается, что второй параметр задаёт путь к папке назначения; в противном случае он задаёт путь к файлу назначения.
Примечание:
В случае указания путей к несуществующим файлам или папкам при выполнении веб-сценария возникнет ошибка. Также ошибка возникнет, если путь к копируемому файлу, содержащий символы-маски, не указывает ни на один файл.
Третий, необязательный, параметр позволяет указать, что веб-сценарий будет делать, если в папке назначения уже присутствует файл с тем же именем, что и копируемый файл. Значение true указывает перезаписать такой файл, а значение false - не перезаписывать. Значение по умолчанию - true (то есть файл будет перезаписан).
Примечание:
Если в папке назначения уже существует файл с тем же именем, что и копируемый, а мы отменили перезапись существующих файлов, то при выполнении веб-сценария возникнет ошибка.
Метод CopyFile не возвращает результата.
oFSO.CopyFile("c:\\Work\\*.exe", "c:\\Dists");
Копируем все исполняемые файлы из папки Work в папку Dists диска C. Поскольку мы указали в пути к копируемому файлу символ-маску *, второй параметр метода CopyFile задаст путь к папке назначения.
oFSO.CopyFile("c:\\Work\\testfile.txt", "c:\\Work\\Temp\\");
Копируем файл testfile.txt из папки Work в папку Work\Temp диска C. Обратим внимание, что мы завершили путь к папке назначения символом обратного слеша, тем самым указав, что это именно путь к папке, а не к файлу.
oFSO.CopyFile("c:\\Work\\testfile.txt", "c:\\Work\\testfile2.txt");
Копируем файл testfile.txt в ту же папку под именем testfile2.txt.
Для перемещения произвольного файла в другую папку предназначен метод MoveFile объекта FileSystemObject. Формат его вызова таков:
<экземпляр объекта FileSystemObject>.MoveFile(
<путь к перемещаемому файлу>,
<путь к файлу или папке назначения>
);
Параметры этого метода аналогичны параметрам уже знакомого нам метода CopyFile, и ведёт он себя так же.
oFSO.MoveFile("c:\\Work\\*.exe", "c:\\Dists");
Перемещаем все исполняемые файлы из папки Work в папку Dists диска C.
oFSO.MoveFile("c:\\Work\\testfile.txt", "c:\\Work\\Temp\\");
Перемещаем файл testfile.txt из папки Work в папку Work\Temp диска C.
oFSO.MoveFile("c:\\Work\\testfile.txt", "c:\\Work\\Temp\\testfile2.txt");
Перемещаем файл testfile.txt из папки Work в папку Work\Temp диска C под именем testfile2.txt, тем самым фактически его переименовывая.
Удалить файл с диска можно вызовом метода DeleteFile объекта FileSystemObject. Формат его вызова таков:
<экземпляр объекта FileSystemObject>.DeleteFile(
<путь к удаляемому файлу>[,
<удалить ли файл с установленным атрибутом "только для чтения">]
);
Первым, обязательным, параметром этому методу передаётся путь к удаляемому файлу. Он должен быть представлен в виде строки. В имени файла, присутствующем в этом пути, можно использовать символы-маски * и ?; то есть мы сможем удалить сразу несколько файлов.
Второй, необязательный, параметр указывает, что делать в случае, если удаляемый файл имеет установленный атрибут "только для чтения". Значение true указывает, что такой файл всё равно следует удалить, а значение false - не делать этого. Значение по умолчанию - false (файлы с установленным атрибутом "только для чтения" удаляться не будут).
Метод DeleteFile не возвращает результата.
Примечание:
При вызове метода DeleteFile файл будет удалён безвозвратно, без помещения в системную Корзину. При попытке удаления несуществующего файла возникнет ошибка. Также ошибка возникнет, если путь к удаляемому файлу, содержащий символы-маски, не указывает ни на один файл.
oFSO.DeleteFile("c:\\Work\\testfile.txt");
Удаляем файл testfile.txt из папки Work диска C.
oFSO.DeleteFile("c:\\Work\\*.txt");
Удаляем все текстовые файлы из той же папки.
2.6. Проверка существования файла
Часто бывает нужно проверить, существует ли на диске файл с указанным путём, перед его открытием или созданием. Для этого мы можем использовать метод FileExists объекта FileSystemObject. В качестве единственного параметра он принимает путь к файлу в виде строки и возвращает true, если файл с этим путём существует, и false в противном случае.
var sFilePath = "c:\\Work\\testfile.txt";
if (oFSO.FileExists(sFilePath))
oFSO.DeleteFile(sFilePath);
2.7. Получение имени временного файла
Другая операция, которую время от времени приходится выполнять, - создание временного файла для хранения каких-либо рабочих данных. Такие временные файлы должны иметь уникальные имена, исключающие конфликты с именами уже существующих на диске файлов. Как правило, имена временных файлов генерируются случайным образом.
Получить такие имя для создания временного файла можно вызовом метода GetTempName объекта FileSystemObject. Этот метод не принимает параметров и возвращает строку со сгенерированным именем файла. Отметим, что, во-первых, оно уже будет включать расширение tmp, а во-вторых, не будет содержать путь, так что временный файл можно будет создать в любой папке.
var sFileName = oFSO.GetTempName();
var oTS = oFSO.CreateTextFile("c:\\Work\\" + sFileName, true);
oTS.WriteLine("Test!!!");
oTS.Close();
Здесь мы получаем имя временного файла, создаём файл с таким именем в папке Work диска C и записываем в этот файл строку "Test!!!". Подробнее о создании текстовых файлов и записи в них рассказывалось в предыдущей статье цикла, посвящённой файловому вводу-выводу.
Дополнительные материалы
Продолжение следует...
Май 2011
По теме
- Видео-курсы от MS: Разработка приложений виртуальной и расширенной реальности на платформе Microsoft
- ECMA JavaScript 6: Объекты
- Как просто создать приложение для iPhone
- Разработка приложений под Windows Phone 8
- Индексированное хранилище, часть 2
- Индексированное хранилище, часть 1
- Начала Metro-программирования: создание настраиваемых приложений (ч.2)
- Начала Metro-программирования: создание настраиваемых приложений (ч.1)
- Начала Metro-программирования: создание компонентов WinRT (ч.3)
- Начала Metro-программирования: создание компонентов WinRT (ч.2)