Опрос
Вы участвуете в программе Windows Insider?
Популярные новости
Обсуждаемые новости

28.04.2011 14:03 | dronov_va

В предыдущих статьях цикла, посвящённого HTML-приложениям Internet Explorer, мы рассматривали, в основном, средства для построения пользовательского интерфейса таких приложений. Мы научились создавать "многооконные" HTML-приложения, получать параметры командной строки и использовать диалоговые окна. Что ж, для создания простых приложений (а HTML-приложения на большее не претендуют) этого хватит.

Настала пора узнать, какие же инструменты предоставляются нам как разработчикам для реализации логики таких приложений. И первое, что мы рассмотрим, - средства для файлового ввода-вывода, то есть чтения из файлов и записи в них.

Примечание:
Перед чтением этой статьи настоятельно рекомендуется ознакомиться с предыдущими статьями цикла, посвящённого HTML-приложениям Internet Explorer.


1. Введение в средства файлового ввода-вывода
Сначала, как водится, - небольшой отвлечённый экскурс в теорию. Все объекты, экземплярами которых мы можем манипулировать в веб-сценариях, делятся на три группы. Рассмотрим их.

  • Объекты, встроенные в саму среду исполнения JavaScript. Это объекты, реализующие базовые типы языка (String, Number, Boolean, Date, Array, Function и Object) и его функциональность (Math, Global и др.).
  • Объекты, реализуемые веб-браузером. К ним относятся все объекты, представляющие саму веб-страницу и её элементы (HTMLDocument, HTMLParagraphElement, HTMLDivElement, HTMLImageElement и др.), а также различные программные интерфейсы самого веб-браузера: окно (Window), сам веб-браузер (Navigator), интернет-адрес веб-страницы (Location) и пр.
  • Внешние объекты. Они не являются частями среды исполнения JavaScript или веб-браузера, а реализуются сторонними по отношению к ним программами. Эти программы регистрируются в системе в качестве компонентов ActiveX.


Так вот, средства файлового ввода-вывода - суть набор как раз внешних объектов. Эти объекты реализуются с помощью особой программы, называемой Windows Scripting Host, или WSH. Обычно они используются клиентских сценариях - программах, написанных на языках JavaScript или VBScript и прямо в среде Windows; такие сценарии обычно используются для автоматизации рутинных задач, как правило, административных. Но эти средства могут применяться также и в HTML-приложениях, чем мы и займёмся в этой статье.

WSH присутствует на всех компьютерах с установленной Windows XP или Internet Explorer 6. Так что отдельно его устанавливать не нужно.

Как уже говорилось, программы, реализующие внешние объекты, регистрируются в системе в качестве компонентов (их ещё называют серверами) ActiveX. WSH - не исключение. Для создания экземпляров таких объектов применяются специальные средства Internet Explorer, которые мы обязательно рассмотрим.

WSH предоставляет довольно много различных объектов, с помощью которых мы можем получать различные сведения о файлах и папках (имя, размер, дату последнего изменения и др.), работать с ними (создавать, копировать, перемещать и удалять), а также записывать информацию в файлы и читать её оттуда. В рамках данной статьи нас больше всего интересует последнее; остальные объекты WSH и предоставляемые ими возможности мы изучим в последующих статьях данного цикла.

На данный момент WSH поддерживает ввод-вывод только для текстовых файлов. Двоичный ввод-вывод с его помощью невозможен, и поддержка его вряд ли появится в будущем. (На взгляд автора, это оправдано - среда исполнения JavaScript вообще не имеет средств для работы с двоичными данными, значит, реализовывать двоичный ввод-вывод нецелесообразно.)

К сожалению, WSH также не имеет средств для вызова стандартных диалоговых окон Windows открытия и сохранения файла. Поэтому нам придётся пользоваться обходными путями, а какими - мы узнаем в этой статье.

На этом "отвлечённая" теория закончена. Займёмся теорией, так сказать, более близкой к практике.


2. Получение доступа к средствам файлового ввода-вывода WSH
Первое, что нам следует сделать, - получить доступ к средствам файлового ввода-вывода, создав экземпляр ключевого объекта WSH, который их реализует. Это объект Scripting.FileSystemObject, или, сокращённо, FileSystemObject.

Все внешние объекты, реализуемые компонентами ActiveX, представляются в Internet Explorer как объекты ActiveXObject. Следовательно, чтобы создать экземпляр внешнего объекта, нам следует создать экземпляр объекта ActiveXObject, указав при этом в качестве параметра его конструктора имя этого самого внешнего объекта.

Экземпляры всех объектов в JavaScript создаются с помощью знакомого нам оператора new. А формат выражения, создающего экземпляр внешнего объекта, таков:

<переменная> = new ActiveXObject(<имя объекта>);

а>);[/code]
Отметим, что в данном случае <имя объекта> указывается в виде строки. Причём имя следует указывать полное, а не сокращённое.

Возвращённый оператором new экземпляр объекта мы обязательно поместим в какую-либо переменную. Нам ведь с ним ещё работать и работать...

[code]var oFSO = new ActiveXObject("Scripting.FileSystemObject");[/code]
Данное выражение поместит в переменную oFSO экземпляр объекта FileSystemObject.


3. Чтение из файла
Итак, экземпляр объекта FileSystemObject, предоставляющий доступ к средствам файлового ввода-вывода WSH, получен. Теперь мы можем прочитать содержимое любого текстового файла или записать в него что-либо.

3.1. Открытие файла для чтения
Перед тем как начать чтение содержимого файла, его следует открыть. А при открытии указать, что мы собираемся именно читать из него.

Открытие файла выполняется вызовом метода OpenTextFile объекта FileSystemObject. Формат его вызова приведён ниже.

[code]<экземпляр объекта FileSystemObject>.OpenTextFile(
<путь файла>,
<режим открытия>[,
<создавать ли файл>[,
<кодировка файла>]]
);[/code]
Первым параметром этому методу передаётся путь к открываемому файлу. Он должен быть указан в виде строки.

Примечание:
Если мы зададим путь к несуществующему файлу и при этом укажем, чтобы файл, в случае его отсутствия на диске, не создавался (об этом - чуть позже), то при выполнении веб-сценария получим сообщение об ошибке.

Вторым параметром указывается режим открытия файла: будет он открыт только для чтения, только для записи или только для дозаписи. Чтобы указать, что файл следует открыть для чтения, в качестве значения этого параметра нужно указать число 1. (Остальные режимы открытия файла мы рассмотрим потом.)

Примечание:
В документации по WSH на веб-сайте MSDN сказано, что второй параметр метода OpenTextFile является необязательным, но не указано его значение по умолчанию. Поэтому автор рекомендует всегда указывать второй параметр.

Третий, необязательный, параметр позволяет указать, следует ли создавать открываемый файл, если он отсутствует на диске. Значение true указывает сделать это, а значение false - не делать. Если данный параметр пропущен, файл создаваться не будет (то есть значение третьего параметра по умолчанию - false).

Четвёртый, также необязательный, параметр указывает кодировку, в которой будет прочитано содержимое открываемого файла. Отметим, что это кодировка, в которой мы будем читать содержимое файла, а не кодировка, в которой оно реально сохранено. Числовое значение 0 задаёт кодировку ASCII, значение -1 - кодировку Unicode, а значение -2 - системную кодировку по умолчанию. Значение по умолчанию - 0 (то есть указывается кодировка ASCII).

Метод OpenTextFile возвращает экземпляр особого объекта TextStream. Этот объект представаляет содержимое открытого текстового файла и позволяет читать его и перемещаться внутри его на заданную позицию. (Кроме того, он позволяет записывать в файл, но об этом позже.)

[code]var oTS = oFSO.OpenTextFile("c:\\Work\\testdata.txt", 1);[/code]
Здесь мы открыли файл testdata.txt, расположенный в папке Work диска C:\.

При указании путей к файлам следует иметь в виду следующее. Для разделения имён папок и файла в путях применяется символ обратного слеша (\). Этот же символ применяется для указания специальный символов (литералов) в строковых значениях JavaScript; например, литерал \" обозначает символ двойной кавычки, который нельзя просто так вставить в строку. Так вот, чтобы поместить в строку именно символ обратного слеша, следует использовать литерал \\ (что мы и сделали в предыдущем примере).

[code]var oTS = oFSO.OpenTextFile("c:\\Work\\testdata.txt", 1, true, -1);[/code]
А здесь мы при открытии того же файла указали, чтобы система создала его, если он в настоящее время отсутствует на диске, и установили, что будет читать его содержимое в кодировке Unicode.

3.2. Чтение содержимого файла
Для чтения содержимого файла применяются три метода объекта TextStream. Сейчас мы их рассмотрим.

Метод ReadLine выполняет чтение отдельной строки вплоть до её окончания. (В системе Windows концом строки считается комбинация символов возврата каретки и перевода строки.) Он не принимает параметров, а возвращает в качестве результата строковое значение, содержащее прочитанную строку без символов возврата каретки и перевода строки.

Здесь важно отметить вот что. Объект TextStream поддерживает особый внутренний указатель, обозначающий позицию в содержимом файла, с которой начнётся следующая операция чтения. Сразу же после открытия файла этот указатель установлен на самый первый символ содержимого; это значит, что самая первая операция чтения из файла начнётся с его первого символа. После выполнения операции чтения этот указатель смещается к концу файла на расстояние, равное количеству прочитанных символов. Следовательно, последующая операция чтения начнётся в том месте, где закончилась предыдущая.

Применительно к методу ReadLine это значит, что при выполнении первого вызова данного метода внутренний указатель будет смещён на расстояние, равное длине первой присутствующей в файле строки - той самой, которая была прочитана при первом вызове. Следующий вызов метода ReadLine прочитает вторую строку и сместит указатель на расстояние, равное длине второй строки, и т. д.

Благодаря такому подходу мы можем считывать содержимое файла, просто вызывая метод ReadLine или любой из двух других методов объекта TextStream, выполняющих чтение из файла. Смещение указателя при этом выполняет за нас сам этот объект.

Примечание:
Если внутренний указатель установлен не на первый символ текущей строки, метод ReadLine вернёт остальную, не прочитанную ещё часть строки.

Если внутренний указатель находится на самом конце файла, то любая попытка чтения вызовет ошибку выполнения веб-сценария. (Програмисты называют такую ситуацию "чтение за концом файла".) Поэтому перед любой потенциально проблемной операцией чтения всегда следует проверять, не достигнут ли конец файла (об этом будет рассказано позже).

[code]var s1 = oTS.ReadLine();
var s2 = oTS.ReadLine();
var s3 = oTS.ReadLine();[/code]
Здесь мы читаем первые три строки открытого файла и помещаем их в переменные.

Если нам нужно прочитать всё содержимое файла за один раз, мы воспользуемся методом ReadAll. Он не принимает параметров и возвращает в содержимое файла в виде строки.

[code]var s = oTS.ReadAll();[/code]
Нам также может пригодиться метод Read. Он считывает из файла указанное количество символов и смещает внутренний указатель на эту величину. В качестве единственного параметра он принимает количество символов, которые следует прочитать, в виде числа, а возвращает строку с прочитанными символами.

Если при вызове метода Read мы укажем количество символов, большее, чем осталось непрочитанными в содержимом файла, данный метод вернёт строку с оставшимися непрочитанными символами. Ошибки при этом не возникнет. А внутренний указатель будет установлен на самый конец файла.

[code]var s4 = oTS.Read(12);[/code]
3.3. Смещение внутреннего указателя файла на произвольную позицию
Часто бывает необходимо сместить внутренний указатель файла, так сказать, вручную. Для этого применяются два особых метода объекта TextStream.

Метод SkipLine смещает внутренний указатель к концу файла на расстояние, равное длине текущей строки. Другими словами, он пропускает текущую строку, не читая её. Этот метод не принимает параметров и не возвращает результата.

[code]oTS.SkipLine();
oTS.SkipLine();[/code]
Этот код пропускает две строки в содержимом файла.

Метод Skip пропускает заданное количество символов, которое указывается в качестве единственного параметра в числовом виде. Результата этот метод не возвращает.

[code]oTS.Skip(30);[/code]
Примечание:
Мы можем сместить внутренний указатель за пределы конца файла - никакой ошибки при этом не возникнет, а указатель реально будет установлен на конец файла.

К большому сожалению, мы не можем указывать в качестве параметра метода Skip отрицательные числа, чтобы таким образом сместить внутренний указатель к началу файла. При попытке сделать это мы тотчас получим сообщение об ошибке.

Если же нам потребуется быстро сместить внутренний указатель на самое начало файла, лучше всего закрыть этот файл (как это сделать, мы узнаем позже) и сразу же открыть.

3.4. Получение текущей позиции внутреннего указателя файла
А ещё объект TextStream позволяет узнать текущую позицию внутреннего указателя файла. Для этого применяются четыре доступных только для чтения свойства, которые мы сейчас рассмотрим.

Свойство Column возвращает номер символа в строке, на которой в данный момент установлен внутренний указатель, в виде числа. А свойство Line возвращает номер строки, на которой в данный момент установлен внутренний указатель, также в виде числа.

[code]var iColumn = oTS.Column;
var iLine = oTS.Line;[/code]
Сразу после открытия файла, когда внутренний указатель установлен на самый первый символ его содержимого, свойства Column и Line хранят значение 1.

Свойство AtEndOfLine возвращает true, если внутренний указатель находится на конце строки, и false в противном случае.

[code]var s = "";
while (!(oTS.AtEndOfLine))
s += oTS.Read(1);[/code]
Этот код посимвольно считывает текущую строку. (Конечно, для этой цели лучше воспользоваться методом ReadLine, но это просто пример.)

Аналогично, свойство AtEndOfStream возвращает true, если внутренний указатель находится на конце содержимого файла, и false в противном случае.

[code]var s = "";
while (!(oTS.AtEndOfStream))
s += oTS.ReadLine();[/code]
Этот код построчно считывает всё содержимое файла. (Хотя, разумеется, метод ReadAll подходит для этого не в пример лучше.)

3.5. Закрытие файла после чтения
После завершения всех операций по чтению из файла его следует закрыть. При этом будут освобождены все системные ресурсы, отведённые под открытый файл и поддержку всех операций чтения из него.

Для закрытия файла применяется метод Close объекта TextStream. Он не принимает параметров и не возвращает результата.

[code]oTS.Close();[/code]

4. Запись в файл
Теперь рассмотрим, как выполняется процесс записи в файл.

4.1. Открытие файла для записи
Опять же, перед тем как начать записывать в файл, его следует либо открыть (если файл уже существует), либо создать (если его ещё нет на диске).

Открытие файла на запись выполняется уже знакомым нам по параграфу 3.1 методом OpenTextFile объекта FileSystemObject. Единственное - нам будет нужно указать соответствующий режим открытия файла.

Как мы уже знаем, режим открытия файла задаётся вторым параметром метода OpenTextFile. Значение 1 этого параметра указывает открыть файл для чтения.

Если мы укажем в качестве значения второго параметра число 2, файл будет открыт для записи. При этом, как только мы откроем файл, предыдущее содержимое файла будет потеряно - файл будет перезаписан.

Если же мы укажем во втором параметре число 8, файл будет открыт для дозаписи. Предыдущее содержимое файла при этом потеряно не будет; все строки и символы, что мы запишем в этот файл, будут добавлены к нему.

[code]var oTS = oFSO.OpenTextFile("c:\\Work\\testdata.txt", 2);[/code]
Здесь мы открываем файл testdata.txt, расположенный в папке Work диска C, для записи. Данный файл будет перезаписан.

[code]var oTS = oFSO.OpenTextFile("c:\\Work\\testdata.txt", 8, true);[/code]
А здесь мы открываем тот же файл для дозаписи и одновременно указываем, чтобы данный файл, если он ещё не существует, был создан. Такой приём, кстати, можно применить для создания файла журнала (лога).

4.2. Создание файла с одновременным открытием для записи
Как мы уже знаем, для создания файла, если он ещё не существует на диске, следует указать в качестве значения третьего параметра метода OpenTextFile логическую величину true. Однако объект FileSystemObject предоставляет нам другой способ сделать это.

Метод CreateTextFile объекта FileSystemObject создаёт текстовый файл и одновременно открывает его для записи. Формат вызова этого метода таков:

[code]<экземпляр объекта FileSystemObject>.CreateTextFile(
<путь файла>[,
<перезаписать ли файл>[,
<кодировка файла>]]
);[/code]
Первым параметром этому методу передаётся путь к открываемому файлу. Он должен быть указан в виде строки.

Примечание:
Если мы зададим путь к уже существующему файлу и при этом укажем, чтобы файл не перезаписывался (об этом - чуть позже), то при выполнении веб-сценария получим сообщение об ошибке.

Второй, необязательный, параметр позволяет указать, следует ли перезаписать файл в случае, если он уже имеется на диске. Значение true указывает, что файл следует перезаписать, а значение false - нет. Значение по умолчанию - false (то есть уже имеющийся файл перезаписан не будет).

На взгляд автора, при любом вызове метода CreateTextFile лучше указать, чтобы существующий файл перезаписывался. Так мы исключим возникновение ошибок. (Также можно перед созданием файла проверять, существует ли он; как это сделать, будет рассказано потом.)

Третий, также необязательный, параметр задаёт кодировку, в которой будет выполняться запись в файл. Значение true задаёт кодировку Unicode, а значение false - ASCII. Значение по умолчанию - false (кодировка ASCII).

Метод CreateTextFile возвращает экземпляр объекта TextStream, с помощью которого и будет выполняться запись в файл.

[code]var oTS = oFSO.CreateTextFile("c:\\Work\\testdata.txt", true);[/code]
Открываем файл testdata.txt из папки Work диска C и указываем, чтобы в случае, если он уже присутствует на диске, он был перезаписан.

4.3. Запись в файл
Для выполнения записи в файл строковых данных объект TextStream предоставляет три метода, разговор о которых пойдёт в этом параграфе.

Метод Write записывает в файл строку, которая передана ему единственным параметром. Никаких дополнительных символов, наподобие признака конца строки (который есть комбинация символов возврата каретки и перевода строки) при этом добавлено не будет. Результата этот метод не возвращает.

[code]oTS.Write("Test!!!");[/code]
Метод WriteLine записывает в файл строку, которая передана ему единственным параметром, и добавляет в её конец признак конца строки. Если вызвать этот метод без параметров, он просто запишет в файл признак конца строки. Результата этот метод не возвращает.

[code]oTS.WriteLine("Test!!!");[/code]
Записываем в файл строку "Test!!!", завершая её признаком конца строки.

[code]oTS.WriteLine();[/code]
А здесь мы записываем в файл признак конца строки. Таким образом мы можем записать в файл пустую строку.

Полезность метода WriteBlankLines вызывает сомнение. Он позволяет записать в файл несколько признаков конца строки - их количество указывается в качестве единственного параметра в виде целого числа. Результата этот метод также не возвращает.

[code]oTS.WriteBlankLines(3);[/code]
Записываем в файл три пустые строки.

4.4. Особенности процесса записи в файл
При выполнении записи в файл следует учесть некоторые особенности.

Во-первых, внутренний указатель всегда находится на конце файла. Сместить его вызовом методов Skip и SkipLine объекта TextStream (см. параграф 3.3) мы не сможем - попытка вызова любого из этих методов приведёт к возникновению ошибки.

Во-вторых, свойства AtEndOfLine и AtEndOfStream объекта TextStream (см. параграф 3.4) при записи в файл не работают; попытка обращения к любому из них приведёт к возникновению ошибки. (Что вполне логично, поскольку внутренний указатель и так установлен на самом конце файла.)

В-третьих, мы всё-таки сможем узнать, на какой строке и символе внутри этой строки установлен внутренний указатель. Свойства Column и Line объекта TextStream в режимах записи и дозаписи прекрасно работают.

4.5. Закрытие файла после записи
После завершения всех операций по записи в файл его также следует закрыть. При этом записанные в него данные будут сохранены на диске, а также будут освобождены все системные ресурсы, отведённые под открытый файл и поддержку всех операций записи в него.

Для закрытия файла применяется уже знакомый нам метод Close объекта TextStream.

[code]oTS.Close();[/code]

Дополнительные материалы


Окончание следует...


dronov_va, TheVista.Ru Team
Апрель 2011

Комментарии

Не в сети

Для бинарного ввода/вывода (в том числе FileSystem<->HTTP) был очень удобен механизм ADODB.Stream (.Type = 1; // adTypeBinary).
Правда, антивирусы на дух не переносят скрипты с ним. А было очень удобно.

28.04.11 19:47
0
Не в сети

2 Dark_Diver: Ну ещё бы... Штука потенциально опасная - таким способом можно записать в систему вирус прямо с Web-страницы.

29.04.11 09:23
0
Для возможности комментировать войдите в 1 клик через

По теме

Акции MSFT
420.55 0.00
Акции торгуются с 17:30 до 00:00 по Москве
Все права принадлежат © ms insider @thevista.ru, 2022
Сайт является источником уникальной информации о семействе операционных систем Windows и других продуктах Microsoft. Перепечатка материалов возможна только с разрешения редакции.
Работает на WMS 2.34 (Страница создана за 0.038 секунд (Общее время SQL: 0.015 секунд - SQL запросов: 57 - Среднее время SQL: 0.00026 секунд))
Top.Mail.Ru