На сегодняшний день музыкальные магазины online, наподобие Musikload[1], становятся все более распространенными и пользуются бешенной популярностью. В этой статье мы расскажем как можно читать мета-информацию mp3-файла средствами PHP, что поможет вам в создании каталога музыки. Это очень просто, поддержка базы данных не нужна.
Откуда знает MP3-Player, например Winamp информацию об исполнителе или названии композиции, которую он проигрывает? Может быть, он сам каким-то чудным образом узнает название песни и альбома? Нет, здесь нет никакого волшебства! Подобная информация содержится в самих файлах. Музыкальные файлы других форматов таких как WMA или Ogg Vorbis также содержат подобную информацию, но здесь речь пойдет о файлах в формате mp3.
Спецификация mp3 определяет способ хранения музыкальных данных, однако не предусматривает никакой возможности для сохранения метаданных композиции, таких как название и исполнитель. Чтобы обойти это ограничение был разработан стандарт ID3. Согласно этой спецификации, метаданные должны быть помещены в так называемые ID3-теги, которые независимо от используемого стандарта ID3, помещаются в конец или начало файла. ID3-теги версии 1 (ID3v1-Tags) представляют собой простейшую конструкцию, которая дописывается в конец файла. Ее объем не должен превышать 128 байт. Структура тега такова: после строкового значения “TAG» следует информация о названии (30 символов), исполнителе (30 символов), альбоме (30 символов), годе записи (четырехзначное число), комментарий (30 символов), жанр (1 байт). Тег с подобной структурой обозначается как ID3v1.0-Tag. В дополнение к этому существует еще стандарт ID3v1.1-Tag, который встречается значительно чаще, поскольку позволяет сохранять информацию о порядковом номере композиции в альбоме. Вследствие этого был урезан до 28 символов размер комментария. Сразу после комментария следует нуль-байт, а последующий байт содержит информации о номере трэка. На иллюстрации один и два видна структура обоих стандартов.
PEAR придет на помощь!
Для считывания информации из ID3v1 тегов, в библиотеку PEAR уже был включен пакет MP3_Id[3], который поможет Вам без проблем извлекать информацию из тега, или наоборот записывать. Если в файл отсутствует ID3-тег, вы можете его создать. Листинг 1 показывает как можно считывать информацию из тегов. Создается объект класса MP3_ID, считывается файл, а затем метод getTag() извлекает данные, которые помещаются для дальнейшей обработки в отдельные поля объект. Листинг 2 показывает результат действия программы листинга 1. Общий обзор доступных полей вы найдете в документации по пакету на домашней странице PEAR.
Листинг 1:
Листинг 2:
Листинг 3 показывает как просто можно изменять содержимое ID3-тегов и создавать их. Сначала, как это было показано в Листинге 1, создаем объект класса MP3_ID, считываем файл, а с помощью метода setTag($fieldname, $value) помещаем в тег нужную информацию. Хотите удалить все теги? Тогда посмотрите на листинг 4, где показано как можно сделать это. Для удаления тегов используется метод remove(), а остальное вы уже знаете. Необходимо дополнить, что MP3_Id обладает другими полезными функциями, которые вам позволят перенести содержимое тега из одного файла в другой или сформировать массив, содержащий все музыкальные направления. Для получения дополнительной информации смотрите документацию.
Listing 3:
Listing 4:
Используем PECL
В конце лета 2004 года появилось расширение PHP ext/id3[7]. Разрабатывается в рамках PECL[6]. В отличие от MP3_ID эта библиотека написана не на PHP, а на C, поэтому она должно работать несколько быстрее. Однако библиотека не входит в стандартный комплект PHP-исходников, к тому же на сегодняшний день отсутствует стабильная версия, хотя функции отвечающие за чтение и запись ID3-тегов считаются стабильными.
Если вы хотите использовать именно это расширение, для установки необходимо воспользоваться либо PEAR-installer, либо откомпилировать php, включив поддержку данного расширения. Если вы используете WINDOWS, существует возможность скачать уже откомпилированную DLL для версии php 5.0 или 5.01 с сайта PHP-Snapshot[9], поместить ее в каталог с расширениями php (например c:phpext), подключить через php.ini. Чтобы воспользоваться расширением, вы должны иметь PHP 4.3 или более позднюю версию, поскольку библиотека использует Streams-API.
Само собой разумеется, библиотека позволяет изменять содержимое ID3-тегов. Для этого вам не нужно ничего, кроме массива, представленного в листинге 6, и функции id3_set_tag(). В качестве первого параметра функция принимает имя изменяемого mp-3 файла, а в качестве второго - массив с необходимыми данными. Третий параметр необязателен и представляет собой константу, указывающую версию ID3-тега. В существующей версии библиотеки функция id3_set_tag() может работать только с тегами версии 1.0 или 1.1. Листинг 7 содержит необходимый php-код. В дополнение к этому, листинг 8 показывает как с помощью функции id3_remove_tag можно удалить существующий ID3-тег.
Ext/id3 содержит еще несколько полезных функций, которые позволяют определить версию ID3-тега (id3_get_version) или манипулируют со списком музыкальных направлений и их id, представленных в виде целого числа типа integer. Надо сказать, что данное число мало подходит для указания музыкального направления.
Listing 5:
Listing 6:
Listing 7:
Следующее поколение
Несмотря на то, что с помощь ID3v1-тегов уже можно сохранять важнейшую информацию о содержимом mp3-файла, уже проявляются ограничения версий 1.0 и 1.1:
из-за фиксированного размера тега ограничен объем сохраняемой информации
ограничено количество сохраняемых атрибутов
Как мы видим, расширить объем пространства, отведенный под ID3v1 теги нельзя, Существую трудности с сохранением информации о названии композиции, исполнителе, альбоме, комментарии, если размер данных превышает 30 символов. Допустим, вам нужно указать название The Hitchhiker's Guide to the Galaxy, используя стандарт ID3v1, вы можете сохранить лишь The Hitchhiker's Guide to. Та же ситуации наблюдается с указанием музыкального направления. Для этого выделяется только один байт, вследствие этого количество музыкальных направлений не может превышать 256. Наверное, сегодня этого достаточно, но кто знает, сколько в будущем появится еще музыкальных направлений.
Чтобы преодолеть указанные ограничения был введены ID3-теги версии 2[2], или короче ID3v2. ID3v2-теги записываются в начало файла, собственно перед самими аудио данными. Информация организована в отдельные единицы, которые обозначаются как фреймы. ID3v2 - это формат-контейнер, то есть, существует возможность при изменении тега вводить новые фреймы. Из этого следует, что ID3v2 может содержать значительно больше информации, чем ID3v1. Это может быть информация об авторских правах, битрейте, (BMP) или, наконец, полный текст песни или изображения. В дополнение к этому можно по желанию добавлять новые фреймы. Вот важнейшие достоинства данного формата:
Никаких ограничений на объем сохраняемой информации
Гибкость и расширяемость
Возможность сжатия содержимого тегов
Поддержка Unicode
Возможность хранить бинарные данные, например изображения и файлы.
Из-за расширенных возможностей ID3v2-теги, несколько труднее поддаются считыванию, чем ID3v1-теги. Хорошая новость состоит в том, что ext/id3 уже позволяет извлекать важнейшую информацию. Если вы исполните код, помещенный в листинг 9, вы получите тот же результат, что и в листинге 10. Проделав это, вы сможете убедиться, что объем выводимых данных значительно шире, чем тот, что показан в листингах 5 и 6.
Каждый фрейм ID3v2-тега обладает уникальным ID. Ext/id3 содержит две функции, которые позволяют узнать содержимое фрейма. Это id3_get_frame_short() и id3_get_frame_long_name(). В качестве параметра они принимают id фрейма и возвращают его описание.
В будущих версиях ext/id3 будет содержать другие полезные функции, которые позволят считывать или записывать фреймы, соответствующие спецификации ID3.
Листинг 8:
Listing 9:
Дополнительная информация
Прежде чем вы организуете бизнес, связанный с продажей музыкальных композиций online, мы вам расскажем еще о нескольких полезных возможностях библиотеки MP3_Id. С помощью нее можно не только считывать информацию ID3- тегов, она позволяет получить некоторую интересную информацию о самом mp3-файле. Речь идет о битрейте, длительности звучания и других полезных свойствах. Подобные сведения можно получить при помощи метода study(), а дальше посредством метода getTag(), можно выбирать необходимые данные. Листинг 12 показывает как это работает. Результат работы программы показан в листинге 13. К сожалению, эти возможности недостаточно документированы, т.е. трудно разобраться какой атрибут можно считать при помощи getTag() или изменить посредство setTag(). В этом случае необходимо изучить код модуля MP3/Id.php.
Listing 10:
Listing 11:
Listing 12:
Listing 13:
Выводы
В этой статье мы рассмотрели существующие возможности извлечения информации из mp-3 файлов средствами PHP. Обе библиотеки (MP3_Id и id3) легки в использовании и содержать необходимые функции. Одна библиотека написана на PHP, другая на C. Выбор того или иного варианта определяется вашими предпочтениями и возможностями хостинга.
Авторы
Карстен Луке изучает информатику в высшей школе Бранденбурга. Совместно со Стефаном Шмидтом разработывает расширение id3. Вы можете связаться с ним по e-mail ( luckec@php.net ) или посетить его сайт ( www.tool-gerade.de ) Стефан Шмидт - разработчик веб-приложений фирмы 1&1 Internet AG, активно учавствует в развити PEAR и PECL. Вы можете связаться с ним по e-mail ( schst@php.net )
Зачастую на Web – сайтах можно встретить страницы с размещенными на них HTML - формами. Веб-формы – удобный способ получения информации от посетителей вашего сайта. Пример тому – гостевая книга, – которая обеспечивает обратную связь с посетителями и разработчиками сайта. Формы так же удобны и для разработчиков сайта при разработке CMS, которая позволяет поддерживать главное свойство сайта - актуальность. Данная статья посвящена основам создания HTML-форм, их обработке и способам передачи данных из экранных форм в PHP-сценарии.
1) Создание простой формы
Теги <form> и </form> задают начало и конец формы. Начинающий форму тег <form> содержит два атрибута: action и method. Атрибут action содержит адрес URL сценария, который должен быть вызван для обработки сценария. Атрибут method указывает браузеру, какой вид HTTP запроса необходимо использовать для отправки формы; возможны значения POST и GET.
Замечание Главное отличие методов POST и GET заключается в способе передачи информации. В методе GET параметры передаются через адресную строку, т.е. по сути в HTTP-заголовке запроса, в то время как в методе POST параметры передаются через тело HTTP-запроса и никак не отражаются на виде адресной строки.
2) Флажок (checkbox)
Флажки checkbox предлагаю пользователю ряд вариантов, и разрешает выбор нескольких из них.
Группа флажков состоит из элементов <input>, имеющих одинаковые атрибуты name и type(checkbox). Если вы хотите, чтобы элемент был отмечен по умолчанию необходимо пометить его как checked. Если элемент выбран, то сценарию поступит строка имя=значение, в противном случае в обработчик формы не придет ничего, т.е. не выбранные флажки вообще никак не проявляют себя в переданном наборе данных.
Пример:
3) Переключатель(radio)
Переключатели radio предлагают пользователю ряд вариантов, но разрешает выбрать только один из них.
Переключатель (radio) имеет атрибуты name, type и value. Атрибут name задает имя переключателя, type задает тип radio, а атрибут value задает значение. Если пользователь выберет переключатель, то сценарию будет передана строка имя=значение. При необходимости можно указать параметр checked, который указывает на то, что перключатель будет иметь фокус (т.е. будет отмечен по умолчанию) при загрузке страницы. Переключатели также можно объединять в группы, для этого они должны иметь одно и тоже имя.
Пример:
4) Кнопка сброса формы(Reset)
При нажатии на кнопку сброса(reset), все элементы формы будут установлены в то состояние, которое было задано в атрибутах по умолчанию, причем отправка формы не производиться.
Пример:
5) Выпадающий список (select)
Тэг <select> представляет собой выпадающий или раскрытый список, при этом одновременно могут быть выбраны одна или несколько строк.
Список начинается с парных тегов <select></select>. Теги <option></option> позволяют определить содержимое списка, а параметр value определяет значение строки. Если в теге <option> указан параметр selected, то строка будет изначально выбранной. Параметр size задает, сколько строк будет занимать список. Если size равен 1, то список будет выпадающим. Если указан атрибут multiple, то разрешено выбирать несколько элементов из списка(при size = 1 не имеет смысла).
При передаче данных выпадающего списка сценарию передается строка имя=значение, а при раскрытом списке передается строка имя=значение1&имя=значение2&имя=значениеN.
6) Текстовое поле (text)
Позволяет пользователям вводить различную информацию.
При создании обычного текстового поля размером size и максимальной допустимой длины maxlength символов, атрибут type принимает значение text. Если указан параметр value, то поле будет содержать отображать value-текст. При создании поля не забывайте указывать имя поля, т.к. этот атрибут является обязательным.
Пример:
7) Поле для ввода пароля (password)
Полностью аналогичен текстовому полю, за исключением того что символы, набираемые пользователем, не будут отображаться на экране.
Пример:
8) Многострочное поле ввода текста (textarea)
Многострочное поле ввода текста позволяет отправлять не одну строку, а сразу несколько. По умолчанию тег создает пустое поле шириной в 20 символов и состоящее из двух строк.
Многострочное поле ввода текста начинается с парных тегов <textarea></textarea>. Тэг name задает имя многострочного поля. Также можно указать ширину поля(cols) и число строк(rows). При необходимости можно указать атрибут readonly, который запрещает редактировать, удалять и изменять текст, т.е. текст будет предназначен только для чтения. Если необходимо чтобы текст был изначально отображен в многострочном поле ввода, то его необходимо поместить между тэгами <textarea></textarea>.
Пример:
9) Скрытое текстовое поле
Позволяет передавать сценарию какую то служебную информацию, не отображая её на странице.
Скрытое поле начинается с тега <input>, атрибуты которого являются name, type и value. Атрибут name задает имя поля, type определяет тип поля, а атрибут value задает значение поля.
Пример:
10) Кнопка отправки формы (submit)
Служит для отправки формы сценарию.
При создании кнопки для отправки формы необходимо указать 2 атрибута: type=“submit” и value=”Текст кнопки”. Атрибут name необходим если кнопка не одна, а несколько и все они созданы для разных операций, например кнопки "Сохранить", "Удалить", "Редактировать" и т.д. После нажатия на кнопку сценарию передается строка имя=текст кнопки.
11) Кнопка для загрузки файлов (browse)
Служит для реализации загрузки файлов на сервер. Объект browse начитается с парных тегов <form></form>. Начинающий тэг <form> содержит необходимый атрибут encrypt. Атрибут encrypt принимает значение multipart/form-data, который извещает сервер о том, что вместе с обычной информацией посылается и файл. При создании текстового поля также необходимо указать тип файла – “file”.
12) Рамка (fieldset)
Объект fieldset позволяет вам нарисовать рамку вокруг объектов. Имеет закрывающий тэг </fieldset>. Заголовок указывается в тэгах <legend></legend>. Основное назначение объекта – задавание различных стилей оформления.
Пример:
Обработка форм
Все данные, которые вы хотите получить из HTML-формы в PHP сценарий обрабатываются с помощью суперглобальных массивов $_POST или $_GET, в зависимости от указанного в атрибуте method метода передачи данных.
Задача: Вам необходимо получить данные из текстового поля и многострочного поля ввода и передать их сценарию.
Решение: Необходимо создать HTML форму и PHP – сценарий для обработки формы.
Обсуждение:
Создадим два файла: form.html и action.php. В файле form.html будет содержаться html-форма с текстовым полем mytext и текстовой областью msg:
В этой html-форме нас интересует 3 атрибута: action который указывает путь к обработчику формы, имя текстового поля (mytext) и имя многострочного поля вода (msg). Также в форме присутствует кнопка, при нажатии на которую происходит передача данных.
После того как html-форма готова нам необходимо создать обработчик формы action.php:
После того как мы введем любые значение в текстовые поля и нажмем на кнопку "Отправить данные" html-форма отправить значения сценарию action.php.
После этого в переменных $text и $msg будут содержаться значения текстового поля и многострочного поля ввода соответственно, значения которых взяты из суперглобальных переменных $_POST.
Если вы хотите, чтобы в многострочном текстовом поле соблюдалось html-форматирование, то используйте функцию nl2br():
Задача: Пусть необходимо создать выпадающий список с годами с 2000 по 2050.
Решение: Необходимо создать HTML форму c элементом SELECT и PHP – сценарий для обработки формы.
Обсуждение:
Для начала создадим два файла: form.html и action.php. В файле form.html будет содержаться html-форма с выпадающим списком. Причем значения в списке можно указать двумя способами:
I. Ввод данных вручную:
II. Ввод данных через цикл:
Как видно, второй пример с циклом, более компактный. Думаю, не стоит приводить скрипт обработчика данной формы, потому что он обрабатывается точно так же как текстовое поле, т.е. значения списка можно извлечь из суперглобального массива $_POST.
Задача: Загрузка файла на сервер
Решение: Необходимо создать HTML форму и PHP – сценарий для обработки файла.
Описание:
Создадим HTML-форму для отправки файла на сервер.
В данной html-форме присутствует элемент browse, который открывает диалоговое окно для выбора файла для загрузки на сервер. При нажатии на кнопку "Передать файл", файл передается сценарию-обработчику.
Затем необходимо написать сценарий обработчик action.php. Перед написание обработчика необходимо определиться в какой каталог мы будет копировать файл:
Замечание Если вы доверяете пользователям закачивать на ваш сервер любые файлы, нужно быть предельно осторожным. Злоумышленники могут внедрить «нехороший» код в картинку или файл и отправить на сервер. В таких случаях нужно жестоко контролировать загрузку файлов.
Данный пример демонстрирует создание каталога и копирование файла в этот каталог на сервер.
Также хотел бы продемонстрировать пример с элементом checkbox. Этот элемент немного отличается от других элементов тем, что если не один из элементов checkbox’a не выбран, то суперглобальная переменная $_POST вернет пустое значение:
Конечно же вы попадали в такую ситуацию, когда приложение, разработанное вами ранее, могло быть снова использовано в рамках другого проекта. Вначале вы конечно же подумали, что это не создаст никаких проблем. Всего-то необходимо скопировать код из одного каталога в другой! Со временем вы осознали, что проекты могут различаться между собой различными параметрами, пусть даже самыми незначительными. Например, это может быть e-mail адрес на который отсылаются сообщения. В таком случае вам ничего не остается, как открыть множество файлов в редакторе и изменить их содержимое, вставляя нужный e-mail при помощи функции найти/заменить. Эта статья расскажет вам о том, как можно избавить себя от подобной работы, а так же порекомендует ряд дополнительных средств для создания и чтения конфигурационных файлов.
Повторное использование кода
Компьютер был изобретен для того, чтобы избавить человека от лишней работы. Развитие компьютерных технологий привело к тому, что человек стал стремиться все меньше времени проводить за компьютером. Допустим, вы программист. Не будь компьютера, вы бы остались без работы. Но в то же время вы стараетесь с помощью компьютера упростить свою ежедневную работы, с этой целью вы используете, например, функцию автозавершения кода в редакторе. Мы хотим подвести вас к той мысли, что код созданный вами, должен быть организован так, чтобы работы по его модификации были сведены к минимуму. Чаще всего это удается, когда вы создаете код, автоматизирующий рутинные операции, такие как создание и прорисовка формы, а так же отправка e-mail. Однако не стоит забывать, что функции для выполнения рутинных операций никогда не бывают на 100% идентичными в различных приложениях. Один формуляр не похож на другой, а сообщения электронной почты предназначены разным адресатам. Однако логика на уровне приложения остается прежней, функции различаются между собой только некоторыми параметрами. Таким образом, вы должны ясно представлять свою цель – разработать код, параметры которого можно было бы определять извне.
Модульная организация
Для решения этой задачи, планируя структуру приложения, вы должны позаботиться о модульности. То есть вам необходимо поместить часто используемые функции или классы в отдельный файл, который будет подключаться через require_once. В этом случае файлы приложения не будут наполнены избыточным кодом. Допустим, вы часто осуществляете запись в лог-файл. В таком случае было бы неплохо код, выполняющий эту операцию, заключить в рамки класса или функции. Будет еще лучше, если вы воспользуетесь уже готовым классом, взятым из какой-нибудь библиотеки исходных кодов, например PEAR.
Параметры процедурального кода
После того, как вы проанализировали код, выделили повторяющиеся фрагменты, распределили их по классам и функциям, необходимо подумать о выделении необходимых параметров, значения которых будут устанавливаться извне. Если речь идет о процедуральном коде, самым простым решением является использование глобальных переменных, которые необходимо определить в отдельном файле. Это позволит в дальнейшем без проблем изменять их значения.
Листинг 1 демонстрирует функцию, которая занимается отправкой e-mail. В ее теле содержится только одна php-функция - mail(). Таким образом, мы избавляемся от необходимости каждый раз указывать получателя при отправке сообщения. Следующая переменная, которую мы определяем, обозначает префикс, предшествующий теме сообщения. Конфигурационный файл, подключаемый через require_once, мог бы выглядеть следующим образом.
Listing 1
Есть способ лучше
Даже если рассмотренный выше способ и является действенным, однако это не самое лучшее решение. По мере того как код вашего приложения будет усложняться, вырастет и число опций, тогда могут возникнуть следующие проблемы:
Глобальные переменные, которые мы используем, могут породить конфликты в пространстве имен.
В том случае, если конфигурационные файлы редактируются не программистом, а дилетантом, в системе могут возникнуть синтаксические ошибки, например из-за незакрытых кавычек.
Для того, чтобы получить доступ к различным переменным, необходимо обращаться к массиву $_GLOBALS.
Вместо php-модулей существуют другие форматы, которые могут быть легко поняты и изменены дилетантами, а так же php-скриптами. Мы имеем в виду два формата: этого широко используемые операционной системой Windows ini-файлы, а так же формат XML.
PHP уже содержит функцию parse_ini_file(), которая без проблем читает ini-файлы. Такой файл имеет очень простую структуру. Каждой опции может быть присвоено только одно значение, а в качестве оператора присваивания используется знак равенства. Конфигурационный файл из предыдущего примера выглядел бы следующим образом в ini-формате.
После считывания ini-файла, имя которого передается в качестве параметра функции parse_ini_file(), мы получаем ассоциативный массив, имеющий вид:
В листинге 2 находится функция отправки почты, основанная на ini-файлах:
Listing 2
Если вы уже прочитали документацию по функции parse_ini_file(), вы кончено же заметили, что она может принимать и второй параметр. Он необходим, если вы хотите разделить ini-файл на несколько разделов или секций. Предположим, вам необходимо сохранить несколько настроек электронной почты. Тогда ini-файл будет выглядеть следующим образом:
"
Если вы при вызове parse_ini_file() передаете true в качестве второго параметра, в этом случае php будет искать в файле секции, а затем вернет многомерный массив, в котором каждой секции (errors и contact) будет соответствовать определенный набор значений:
Особые значения в ini-файлах
При использовании ini-файлов вы должны иметь в виду, что некоторые особые значения могут быть представлены строками. Допустим, вы определяете значение опции как true или yes (без кавычек), в таком случае они автоматически конвертируются в число 1, а false или no – в пустую строку. К сожалению, при этом не генерируется никакой ошибки. Поэтому не пытайтесь использовать no для сокращенного обозначения Норвегии.
Listing 3
Безопасность
Вы должны понимать то, что если конфигурационный файл используется для хранения важных данных, например паролей, необходимо позаботиться о том, чтобы содержимое такого файла не попало в web-браузер. Простейший выход из положения заключается в том, чтобы хранить конфигурационные файлы вне корневой директории сайта, например здесь: /etc/myApp/config
Если этого сделать нельзя, в таком случае можно изменить расширение файла. Для конфигурационного файла в формате модуля php необходимо всегда выбирать расширение .php. В этом случае сервер проанализирует php-файл, а пользователь увидит пустую страницу. С ini-файлами такое не пройдет, однако сервер Apache предоставляет возможность защитить данные. Просто поместите в каталог, где хранятся ini файл с именем .htaccess В него нужно поместить следующие строки:
Теперь сервер перестанет выдавать файлы с расширением ini, а опции приложения будут скрыты от пользователей.
Другие средства
Кончено же вы не являетесь единственным разработчиком, который сталкивается с проблемой обеспечения гибкости настроек веб-приложения. Поэтому некоторые программисты уже разработали библиотеки классов, которые переводят работу с конфигурационными файлами на абстрактный уровень, а так же упрощают запись и чтение различных форматов конфигурационных файлов.
PEAR::Config
Одним из классов, который может пригодится при чтении и записи конфигурационных файлов является PEAR::Config [3]. Как и все классы PEAR, PEAR::Config инсталлируется при помощи PEAR-Installer по команде
Этот класс является многоформатным, поскольку работает с конфигурационными файлами в форматах XMIL, ini, Apach-Style (гибрид XML и ini), а также php-массивами. Достоинством данного класса является то, что API для взаимодействия со всеми форматами одинаков. Т.е. логика работы с конфигурационными файлами в формате XML ничем не отличается от логики работы с ini-файлами. Вследствие этого необходимо, чтобы все форматы имели одинаковую структуру. Конфигурационные файлы, с которыми работает PEAR::Config, состоят, как и ini-файлы из секций.
Изменим снова наш пример. Сначала мы создаем объект Config, а затем вызываем его метод parseConfig(). Поскольку метод позволяет считывать различные форматы файлов, при вызове его необходимо передавать параметр, уточняющий формат. Для конфигурационных файлов в формате ini в качестве такого параметра используется строка iniFile. После считывания файла, мы не получаем опции в виде массива, вместо этого создается объект-контейнер, который дает доступ ко всем настройкам. Хотя во многих случаях бывает желательно получить опции в форме массива. Для этого используется метод toArray(). Листинг 4 демонстрирует считывание ini-файла:
Listing 4
С первого взгляда это может показаться несколько запутанным. Однако преимущество данного подхода заключается в том, что один и тот же метод используется для чтения всех форматов файлов, поддерживаемых PEAR::Config. Измененные опции могут быть также сохранены в любом формате:
Листинг 5 содержит код, где серия опций помещается в массив, который затем сохраняется в формате XML. Если вы хотите побольше узнать о PEAR::Config необходимую информацию вы сможете найти в документации по PEAR[5] или в DevShed-Tutorial [6].
Listing 5
patConfiguration
Альтернативным классом для работы с конфигурационными файлами является patConfiguration[7], однако он предназначен исключительно для работы с файлами в формате XML. После скачивания архива, его необходимо распаковать. Сам класс находится в директории include. patConfiguration предварительно определяет Tag-Set, который затем наполняется данными. К тому же этот класс предоставляет возможность указать тип опции: целое число, число с плавающей точкой, булевское значение. Типичный конфигурационный файл, созданный patConfiguration, имеет следующую структуру:
После создания объекта класса, может быть вызван метод parseConfigFile(). Доступ к опциям осуществляется через getConfigValue(). В качестве параметра этот метод может принимать путь к нужной опции. Вернемся к нашему примеру. Допустим, мы хотим получить e-mail адрес, на который высылается сообщение об ошибке. В этом случае используется путь errors.email. Если путь не указан, тогда все параметры передаются в массив. Листинг 6 демонстрирует код, который можно использовать для считывания файлов.
patConfiguration 2.0.0
В данный момент многоформатная версия patConfiguration находится в стадии разработки. Возможно, при публикации статьи эта версия уже станет доступной. Впрочем, самую новую версию для разработчиков вы можете скачать с сайта snaps.php-tools.net/downloaden.
В этом примере вы уже заметили, что внутри тега указывается тип значения. Названия типов идентичны тем, что используются в php-функции settype(). Если тип не указан, тогда значение интерпретируется как строка. Для часто используемых опций можно определить отдельный тег.
Наряду с функцией getConfigValue, существует функция setConfigValue(), с помощью которой можно изменить значение опции. Затем конфигурационный файл может быть заново записан с помощью writeConfigFile() (см листинг 7).
patConfiguration предлагает также серию дополнительных возможностей. Например, наряду с тегами, существует возможность определять атрибуты и пространства имен (Namespace), а к тегу можно привязать внешний файл, таким образом, опции будут распределены по нескольким файлам. Кроме этого patConfiguration включает систему кэширования, благодаря которой пропадает необходимость в многократном считывании конфигурационного файла.
Дополнительную информацию вы сможете найти на PHP Application Tools-Homepage и в patConfiguration-Tutorial на DevShed [8].
Listing 7
Заключение
Забота о гибкости настроек приложения может сберечь много времени, особенно если его компоненты предполагается использовать в других проектах. Вы потратите еще меньше времени, если доверите работу с конфигурационными файлами одному из готовых классов. Выбор между PEAR::Config и patConfiguration зависит от задачи. Преимуществом PEAR::Config является поддержка различных форматов конфигурационных файлов, в то время как patConfiguration прекрасно работает с XML, так же предоставляет ряд дополнительных возможностей. Однако с появлением версии 2.0.0 этот пакет будет иметь одинаковый API для считывания ini и wddx файлов. PHP-массив поддерживаются уже в текущей версии.
Всё что вы когда-либо хотели знать про mysql, php и кодировки, но боялись спросить! Почему кириллица на сайте отображается вопросами? Как правильно настроить сервер mysql для работы с кириллицей? Как поменять кодировку в mysql? Как изменить кодировку в скриптах php? Какую выбрать кодировку? Как сконвертировать базу данных из одной кодировки в другую? Эти и многие подобные вопросы с завидным упорством снова и снова поднимаются на различных форумах уже который год. В этом посте я постарался рассказать что нужно делать чтобы такие проблемы не возникали и дать наиболее эффективные советы на тот случай если они все-таки возникнут.
Mysql, php и кодировки. Источник проблем.
Проблемы с кодировками в Mysql обусловлены историей создания этой программы. Так как разрабатывали mysql - европейцы - для них было естественно выбрать в качестве основной кодировки более удобную для себя latin1. Странно, но и по сей день большинство инсталляций Mysql по умолчанию работают с этой кодировкой что и создает для пользователей кириллицы проблемы с добавлением в базу данных строк на русском и украинском языках - в latin1 эти символы просто отсутствуют.
Поэтому первое что нужно сделать при возникновении проблем с кодировками в mysql - нужно проверить какая кодировка является для данной инсталляции mysql основной. Проверить это можно несколькими способами.
Настройка сервера mysql для нужной кодировки.
* Если вы админ сервера или вы самостоятельно настраиваете собственную mysql на рабочей машине.
Откройте файл конфигурации mysql.ini (/etc/mysql.cnf для os linux) и найдите такие строки.
Вместо “название_кодировки” нужно подставить название той кодировки, которую вы будете использовать. Для текстов на русском и украинском языках можно использовать utf8 или cp1251 (обратите внимание - названия кодировок в mysql пишутся без обычного дефиса!!!). Но я советовал бы использовать только utf8 - так вы себе сэкономите в будущем немало нервов.
Если такие строки в файле конфигурации отсутствуют, то это означает что база данных использует по умолчанию ту кодировку, которая была задана при компиляции. Добавьте в конфиг нужные вам настройки кодировок (примеры ниже) и перезапустите mysql.
Если у вас возникли проблемы с кодировкой на хостинге, где вы не имеете прав администратора, то проверить настройки кодировки для mysql вы сможете другим способом: установите соединение с mysql (при помощи консольной команды mysql или phpmyadmin - как вам удобнее) и выполните такой sql-запрос: show variables like ‘char%’. Этот запрос покажет вам значения переменных mysql, которые имеют отношение к кодировкам. Скорее всего, вы увидите что-то вроде такого
Я специально привел выше пример НЕПРАВИЛЬНО НАСТРОЕННОГО СЕРВЕРА!!! Обратите внимание - в нем используются в разных случаях три(!) разные кодировки. Начинающему веб-программисту в такой ситуации будет сложно добиться корректной работы скрипта. Старайтесь чтобы все переменные были настроены на работу с одной и той же кодировкой. Тогда 99% проблем которые обсуждаются на форумах у вас просто не возникнут. Тут даже не столь важно какую именно кодировку вы выберете - главное чтобы она была везде одинаковой. Но все-таки старайтесь указывать в настройках ту кодировку, которую действительно будете использовать для хранения данных.
Итак, удачный вариант - это если команда show variables like ‘char%’ из абзаца выше покажет вам список одинаковых кодировок для каждой из переменных и еще лучше будет если эта кодировка совпадет с той которую используете вы.
Если же кодировка mysql отличается от вашей - не спешите расстраиваться. Изменить любую из этих переменных вы можете либо глобально, для всех правкой конфигов (если вы администратор сервера), либо только для себя - sql-запросом set character_set_database=utf8 (если вы пользователь). Такой запрос должен будет выполняться из вашего php скрипта сразу после установки соединения с сервером mysql. Ниже пример для установки кодировки utf8 из php скрипта.
Что касается character_set_database - постарайтесь сразу создать базу данных в нужной кодировке (как вариант - отправьте такую просьбу в техподдержку хостинга), тогда вы избежите по крайней мере одного лишнего запроса к mysql во время работы скрипта. Если удастся,то строчку с ‘character_set_database’ из приведенного выше кода можно будет удалить.
Примеры настроек сервера mysql для правильной работы с кодировками.
При правильно настроенном сервере делать запросы из скрипта для установки правильной кодировки уже будет не нужно.
Настройки для utf8
Проверка реальной кодировки в которой хранятся базы данных mysql.
В случае если вы все (и сервер, и php скрипт) настроили правильно, по инструкции выше, но русские буквы все равно не отображаются - проверьте действительно ли ваши строки сохранены в той кодировке, которую вы указали в настройках!!!
Простой способ проверки - сделайте дамп базы данных в sql-формате и откройте его в текстовом редакторе. Sql-формат - это обычный текст. Если ваша база данных mysql в кодировке cp1251 - открывайте в Блокноте. Если utf8 - в любом редакторе с поддержкой Юникода. Пролистайте файл и убедитесь что все надписи с кириллицей нормально читаются и что sql-команды create table и create database, которые встречаются в дампе содержат правильные названия кодировки mysql (той кодировки, которая вами была указана в настройках сервера или в запросах из php-скриптов.
Если кодировка не подходит - сделайте бекап базы на всякий случай, перекодируйте sql-дамп в любом текстовом перекодировщике, замените названия кодировок в файле на правильные и заливайте полученный файл на сервер mysql. Теперь с кодировками все должно быть в порядке.
Для наполнения сайта контентом нужно прежде всего определиться с тематикой вашего сайта и типом информации, которая будет основным содержанием сайта: новости, статьи, обзоры… И в соответствии с этими критериями уже делать выбор откуда будет черпаться информация для сайта. Самый постой и дешевый вариант – это писать статьи, обзоры или новости самостоятельно, но это возможно только в случае наличия у вас свободного времени, желания и самое главное – понимания того, о чем вы пишите. Но в большинстве случаев, через некоторое время это надоедает, становится неинтересным, не хватает времени или проста становится лень это делать… вот тут то вы и задаетесь вопросом: «Где брать контент?»
Вот несколько вариантов ответа на этот вопрос:
Нанять человека (копирайтера), который будет постоянно писать статьи для вашего сайта по заданной вами тематике, с использованием выбранных вами ключевых слов. Но за определенную плату. Обычно цена рассчитывается по объему и качеству текста.
Покупать статьи интересующей вас тематики на биржах готовых статей, таких как TextSale и Content - Market или же можно заказать SEO-тексты у нас. Обычно тексты на таких биржах не блещут особым качеством, потому что большая часть из всего материала является сканированным и распознанным вариантом какой-либо печатной статьи из журнала или книги. Хотя иногда и попадаются и достойные варианты статей, но и цена у них обычно адекватно отличается от средней цены по системе.
Использовать рерайт – из исходного текста статьи получают новую со старым смыслом, стоит обычно значительно дешевле, обычно на 1-2 порядка. Использование данного варианта идеально при маленьком бюджете и сжатых сроках.
Так же можно использовать чужие статьи, новости или обзоры. Но в этом случае на целевых посетителей, которые будут идти из поисковых систем рассчитывать, особо не стоит. Данный вариант только кажется наиболее дешевым, на самом деле, на продвижение такого сайта в поисковых системах понадобится значительно больше сил, времени и денег. Поэтому НЕ СОВЕТУЮ.
Существуют и другие источники контента, о которых говорить думаю, пока не стоит.
В заключении хотелось бы посоветовать начинающим сайто-строителям, писать свои статьи самостоятельно, пусть они будут по началу некрасивые и не звучные, зато написанные вами, и в случае вопросов у посетителей вы всегда сможете на них квалифицированно ответить, не прибегая к консультациям автора вашей статьи.
В этой статье я попытаюсь дать оценку быстродействию файловых систем, используемых в операционных системах WindowsNT/2000. Статья не содержит графиков и результатов тестирований, так как эти результаты слишком сильно зависят от случая, методик тестирования и конкретных систем, и не имеют почти никакой связи с реальным положением дел. В этом материале я вместо этого постараюсь описать общие тенденции и соображения, связанные с производительностью файловых систем. Прочитав данный материал, вы получите информацию для размышлений и сможете сами сделать выводы, понять, какая система будет быстрее в ваших условиях, и почему. Возможно, некоторые факты помогут вам также оптимизировать быстродействие своей машины с точки зрения файловых систем, подскажут какие-то решения, которые приведут к повышению скорости работы всего компьютера.
В данном обзоре упоминаются три системы - FAT (далее FAT16), FAT32 и NTFS, так как основной вопрос, стоящий перед пользователями Windows2000 - это выбор между этими вариантами. Я приношу извинение пользователям других файловых систем, но проблема выбора между двумя, внешне совершенно равнозначными, вариантами со всей остротой стоит сейчас только в среде Windows2000. Я надеюсь, всё же, что изложенные соображения покажутся вам любопытными, и вы сможете сделать какие-то выводы и о тех системах, с которыми вам приходится работать.
Данная статья состоит из множества разделов, каждый из которых посвящен какому-то одному вопросу быстродействия. Многие из этих разделов в определенных местах тесно переплетаются между собой. Тем не менее, чтобы не превращать статью в кашу, в соответствующем разделе я буду писать только о том, что имеет отношение к обсуждаемый в данный момент теме, и ни о чем более. Если вы не нашли каких-то важных фактов в тексте - не спешите удивляться: скорее всего, вы встретите их позже. Прошу вас также не делать никаких поспешных выводов о недостатках и преимуществах той или иной системы, так как противоречий и подводных камней в этих рассуждениях очень и очень много. В конце я попытаюсь собрать воедино всё, что можно сказать о быстродействии систем в реальных условиях.
Теория
Самое фундаментальное свойство любой файловой системы, влияющее на быстродействие всех дисковых операций - структура организации и хранения информации, т.е. то, как, собственно, устроена сама файловая система. Первый раздел - попытка анализа именно этого аспекта работы, т.е. физической работы со структурами и данными файловой системы. Теоретические рассуждения, в принципе, могут быть пропущены - те, кто интересуется лишь чисто практическими аспектами быстродействия файловых систем, могут обратиться сразу ко второй части статьи.
Для начала хотелось бы заметить, что любая файловая система так или иначе хранит файлы. Доступ к данным файлов - основная и неотъемлемая часть работы с файловой системой, и поэтому прежде всего нужно сказать пару слов об этом. Любая файловая система хранит данные файлов в неких объемах - секторах, которые используются аппаратурой и драйвером как самая маленькая единица полезной информации диска. Размер сектора в подавляющем числе современных систем составляет 512 байт, и все файловые системы просто читают эту информацию и передают её без какой либо обработки приложениям. Есть ли тут какие-то исключения? Практически нет. Если файл хранится в сжатом или закодированном виде - как это возможно, к примеру, в системе NTFS - то, конечно, на восстановление или расшифровку информации тратится время и ресурсы процессора. В остальных случаях чтение и запись самих данных файла осуществляется с одинаковой скоростью, какую файловую систему вы не использовали бы.
Обратим внимание на основные процессы, осуществляемые системой для доступа к файлам:
Поиск данных файла
Выяснение того, в каких областях диска хранится тот или иной фрагмент файла - процесс, который имеет принципиально разное воплощение в различных файловых системах. Имейте в виду, что это лишь поиск информации о местоположении файла - доступ к самим данным, фрагментированы они или нет, здесь уже не рассматривается, так как этот процесс совершенно одинаков для всех систем. Речь идет о тех "лишних" действиях, которые приходится выполнять системе перед доступом к реальным данным файлов.
На что влияет этот параметр: на скорость навигации по файлу (доступ к произвольному фрагменту файла). Любая работа с большими файлами данных и документов, если их размер - несколько мегабайт и более. Этот параметр показывает, насколько сильно сама файловая система страдает от фрагментации файлов.
NTFS способна обеспечить быстрый поиск фрагментов, поскольку вся информация хранится в нескольких очень компактных записях (типичный размер - несколько килобайт). Если файл очень сильно фрагментирован (содержит большое число фрагментов) - NTFS придется использовать много записей, что часто заставит хранить их в разных местах. Лишние движения головок при поиске этих данных, в таком случае, приведут к сильному замедлению процесса поиска данных о местоположении файла.
FAT32, из-за большой области самой таблицы размещения будет испытывать огромные трудности, если фрагменты файла разбросаны по всему диску. Дело в том, что FAT (File Allocation Table, таблица размещения файлов) представляет собой мини-образ диска, куда включен каждый его кластер. Для доступа к фрагменту файла в системе FAT16 и FAT32 приходится обращаться к соответствующей частичке FAT. Если файл, к примеру, расположен в трех фрагментах - в начале диска, в середине, и в конце - то в системе FAT нам придется обратиться к фрагменту FAT также в его начале, в середине и в конце. В системе FAT16, где максимальный размер области FAT составляет 128 Кбайт, это не составит проблемы - вся область FAT просто хранится в памяти, или же считывается с диска целиком за один проход и буферизируется. FAT32 же, напротив, имеет типичный размер области FAT порядка сотен килобайт, а на больших дисках - даже несколько мегабайт. Если файл расположен в разных частях диска - это вынуждает систему совершать движения головок винчестера столько раз, сколько групп фрагментов в разных областях имеет файл, а это очень и очень сильно замедляет процесс поиска фрагментов файла.
Вывод: Абсолютный лидер - FAT16, он никогда не заставит систему делать лишние дисковые операции для данной цели. Затем идет NTFS - эта система также не требует чтения лишней информации, по крайней мере, до того момента, пока файл имеет разумное число фрагментов. FAT32 испытывает огромные трудности, вплоть до чтения лишних сотен килобайт из области FAT, если файл разбросан разным областям диска. Работа с внушительными по размеру файлами на FAT32 в любом случае сопряжена с огромными трудностями - понять, в каком месте на диске расположен тот или иной фрагмент файла, можно лишь изучив всю последовательность кластеров файла с самого начала, обрабатывая за один раз один кластер (через каждые 4 Кбайт файла в типичной системе). Стоит отметить, что если файл фрагментирован, но лежит компактной кучей фрагментов - FAT32 всё же не испытывает больших трудностей, так как физический доступ к области FAT будет также компактен и буферизован.
Поиск свободного места
Данная операция производится в том случае, если файл нужно создать с нуля или скопировать на диск. Поиск места под физические данные файла зависит от того, как хранится информация о занятых участках диска.
На что влияет этот параметр: на скорость создания файлов, особенно больших. Сохранение или создание в реальном времени больших мультимедийных файлов (.wav, к примеру), копирование больших объемов информации, т.д. Этот параметр показывает, насколько быстро система сможет найти место для записи на диск новых данных, и какие операции ей придется для этого проделать.
Для определения того, свободен ли данный кластер или нет, системы на основе FAT должны просмотреть одну запись FAT, соответствующую этому кластеру. Размер одной записи FAT16 составляет 16 бит, одной записи FAT32 - 32 бита. Для поиска свободного места на диске может потребоваться просмотреть почти всего FAT - это 128 Кбайт (максимум) для FAT16 и до нескольких мегабайт (!) - в FAT32. Для того, чтобы не превращать поиск свободного места в катастрофу (для FAT32), операционной системе приходится идти на различные ухищрения.
NTFS имеет битовую карту свободного места, одному кластеру соответствует 1 бит. Для поиска свободного места на диске приходится оценивать объемы в десятки раз меньшие, чем в системах FAT и FAT32.
Вывод: NTFS имеет наиболее эффективную систему нахождения свободного места. Стоит отметить, что действовать "в лоб" на FAT16 или FAT32 очень медленно, поэтому для нахождения свободного места в этих системах применяются различные методы оптимизации, в результате чего и там достигается приемлемая скорость. (Одно можно сказать наверняка - поиск свободного места при работе в DOS на FAT32 - катастрофический по скорости процесс, поскольку никакая оптимизация невозможна без поддержки хоть сколь серьезной операционной системы).
Работа с каталогами и файлами
Каждая файловая система выполняет элементарные операции с файлами - доступ, удаление, создание, перемещение и т.д. Скорость работы этих операций зависит от принципов организации хранения данных об отдельных файлах и от устройства структур каталогов.
На что влияет этот параметр: на скорость осуществления любых операций с файлом, в том числе - на скорость любой операции доступа к файлу, особенно - в каталогах с большим числом файлов (тысячи).
FAT16 и FAT32 имеют очень компактные каталоги, размер каждой записи которых предельно мал. Более того, из-за сложившейся исторически системы хранения длинных имен файлов (более 11 символов), в каталогах систем FAT используется не очень эффективная и на первый взгляд неудачная, но зато очень экономная структура хранения этих самих длинных имен файлов. Работа с каталогами FAT производится достаточно быстро, так как в подавляющем числе случаев каталог (файл данных каталога) не фрагментирован и находится на диске в одном месте.
Единственная проблема, которая может существенно понизить скорость работы каталогов FAT - большое количество файлов в одном каталоге (порядка тысячи или более). Система хранения данных - линейный массив - не позволяет организовать эффективный поиск файлов в таком каталоге, и для нахождения данного файла приходится перебирать большой объем данных (в среднем - половину файла каталога).
NTFS использует гораздо более эффективный способ адресации - бинарное дерево, о принципе работы которого можно прочесть в другой статье (Файловая система NTFS). Эта организация позволяет эффективно работать с каталогами любого размера - каталогам NTFS не страшно увеличение количества файлов в одном каталоге и до десятков тысяч.
Стоит заметить, однако, что сам каталог NTFS представляет собой гораздо менее компактную структуру, нежели каталог FAT - это связано с гораздо большим (в несколько раз) размером одной записи каталога. Данное обстоятельство приводит к тому, что каталоги на томе NTFS в подавляющем числе случаев сильно фрагментированы. Размер типичного каталога на FAT-е укладывается в один кластер, тогда как сотня файлов (и даже меньше) в каталоге на NTFS уже приводит к размеру файла каталога, превышающему типичный размер одного кластера. Это, в свою очередь, почти гарантирует фрагментацию файла каталога, что, к сожалению, довольно часто сводит на нет все преимущества гораздо более эффективной организации самих данных.
Вывод: структура каталогов на NTFS теоретически гораздо эффективнее, но при размере каталога в несколько сотен файлов это практически не имеет значения. Фрагментация каталогов NTFS, однако, уверенно наступает уже при таком размере каталога. Для малых и средних каталогов NTFS, как это не печально, имеет на практике меньшее быстродействие.
Преимущества каталогов NTFS становятся реальными и неоспоримыми только в том случае, если в одно каталоге присутствуют тысячи файлов - в этом случае быстродействие компенсирует фрагментированность самого каталога и трудности с физическим обращением к данным (в первый раз - далее каталог кэшируется). Напряженная работа с каталогами, содержащими порядка тысячи и более файлов, проходит на NTFS буквально в несколько раз быстрее, а иногда выигрыш в скорости по сравнению с FAT и FAT32 достигает десятков раз.
Практика
К сожалению, как это часто бывает во всевозможных компьютерных вопросах, практика не очень хорошо согласуется с теорией. NTFS, имеющая, казалось бы, очевидные преимущества в структуре, показывает не настолько уж фантастические результаты, как можно было бы ожидать. Какие еще соображения влияют на быстродействие файловой системы? Каждый из рассматриваемых далее вопросов вносит свой вклад в итоговое быстродействие. Помните, однако, что реальное быстродействие - результат действия сразу всех факторов, поэтому и в этой части статьи не стоит делать поспешных выводов.
Объем оперативной памяти (кэширование)
Очень многие данные современных файловых систем кэшируются или буферизируются в памяти компьютера, что позволяет избежать лишних операций физического чтения данных с диска. Для нормальной (высокопроизводительной) работы системы в кэше приходится хранить следующие типы информации:
Данные о физическом местоположении всех открытых файлов. Это, прежде всего, позволит обращаться к системным файлам и библиотекам, доступ к которым идет буквально постоянно, без чтения служебной (не относящейся к самим файлам) информации с диска. Это же относится к тем файлам, которые исполняются в данный момент - т.е. к выполняемым модулям (.exe и .dll) активных процессов в системе. В эту категорию попадают также файлы системы, с которыми производится работа (прежде всего реестр и виртуальная память, различные .ini файлы, а также файлы документов и приложений).
Наиболее часто используемые каталоги. К таковым можно отнести рабочий стол, меню "пуск", системные каталоги, каталоги кэша интернета, и т.п.
Данные о свободном месте диска - т.е. та информация, которая позволит найти место для сохранения на диск новых данных.
В случае, если этот базовый объем информации не будет доступен прямо в оперативной памяти, системе придется совершать множество ненужных операций еще до того, как она начнет работу с реальными данными. Что входит в эти объемы в разных файловых системах? Или, вопрос в более практической плоскости - каким объемом свободной оперативной памяти надо располагать, чтобы эффективно работать с той или иной файловой системой?
FAT16 имеет очень мало данных, отвечающих за организацию файловой системы. Из служебных областей можно выделить только саму область FAT, которая не может превышать 128 Кбайт (!) - эта область отвечает и за поиск фрагментов файлов, и за поиск свободного места на томе. Каталоги системы FAT также очень компактны. Общий объем памяти, необходимый для предельно эффективной работы с FAT-ом, может колебаться от сотни килобайт и до мегабайта-другого - при условии огромного числа и размера каталогов, с которыми ведется работа.
FAT32 отличается от FAT16 лишь тем, что сама область FAT может иметь более внушительные размеры. На томах порядка 5 - 10 Гбайт область FAT может занимать объем в несколько Мбайт, и это уже очень внушительный объем, надежно кэшировать который не представляется возможным. Тем не менее, область FAT, а вернее те фрагменты, которые отвечают за местоположение рабочих файлов, в подавляющем большинстве систем находятся в памяти машины - на это расходуется порядка нескольких Мбайт оперативной памяти.
NTFS, к сожалению, имеет гораздо большие требования к памяти, необходимой для работы системы. Прежде всего, кэширование сильно затрудняет большие размеры каталогов. Размер одних только каталогов, с которыми активно ведет работу система, может запросто доходить до нескольких Мбайт и даже десятков Мбайт! Добавьте к этому необходимость кэшировать карту свободного места тома (сотни Кбайт) и записи MFT для файлов, с которыми осуществляется работа (в типичной системе - по 1 Кбайт на каждый файл). К счастью, NTFS имеет удачную систему хранения данных, которая не приводит к увеличению каких-либо фиксированных областей при увеличении объема диска. Количество данных, с которым оперирует система на основе NTFS, практически не зависит от объема тома, и основной вклад в объемы данных, которые необходимо кэшировать, вносят каталоги. Тем не менее, уже этого вполне достаточно для того, чтобы только минимальный объем данных, необходимых для кэширования базовых областей NTFS, доходил до 5 - 8 Мбайт.
[pagebreak]
К сожалению, можно с уверенностью сказать: NTFS теряет огромное количество своего теоретического быстродействия из-за недостаточного кэширования. На системах, имеющих менее 64 Мбайт памяти, NTFS просто не может оказаться быстрее FAT16 или FAT32. Единственное исключение из этого правила - диски FAT32, имеющие объем десятки Гбайт (я бы лично серьезно опасался дисков FAT32 объемом свыше, скажем, 30 Гбайт). В остальных же случаях - системы с менее чем 64 мегабайтами памяти просто обязаны работать с FAT32 быстрее.
Типичный в настоящее время объем памяти в 64 Мбайта, к сожалению, также не дает возможности организовать эффективную работу с NTFS. На малых и средних дисках (до 10 Гбайт) в типичных системах FAT32 будет работать, пожалуй, немного быстрее. Единственное, что можно сказать по поводу быстродействия систем с таким объемом оперативной памяти - системы, работающие с FAT32, будут гораздо сильнее страдать от фрагментации, чем системы на NTFS. Но если хотя бы изредка дефрагментировать диски, то FAT32, с точки зрения быстродействия, является предпочтительным вариантом. Многие люди, тем не менее, выбирают в таких системах NTFS - просто из-за того, что это даст некоторые довольно важные преимущества, тогда как типичная потеря быстродействия не очень велика.
Системы с более чем 64 Мбайтами, а особенно - со 128 Мбайт и более памяти, смогут уверенно кэшировать абсолютно всё, что необходимо для работы систем, и вот на таких компьютерах NTFS, скорее всего, покажет более высокое быстродействие из-за более продуманной организации данных. В наше время этим показателям соответствует практически любой компьютер.
Быстродействие накопителя
Влияют ли физические параметры жесткого диска на быстродействие файловой системы? Да, хоть и не сильно, но влияют. Можно выделить следующие параметры физической дисковой системы, которые по-разному влияют на разные типы файловых систем:
Время случайного доступа (random seek time). К сожалению, для доступа к системным областям на типичном диске более сложной файловой системы (NTFS) приходится совершать, в среднем, больше движений головками диска, чем в более простых системах (FAT16 и FAT32). Гораздо большая фрагментация каталогов, возможность фрагментации системных областей - всё это делает диски NTFS гораздо более чувствительными к скорости считывания произвольных (случайных) областей диска. По этой причине использовать NTFS на медленных (старых) дисках не рекомендуется, так как высокое (худшее) время поиска дорожки дает еще один плюс в пользу систем FAT.
Наличие Bus Mastering. Bus Mastering - специальный режим работы драйвера и контроллера, при использовании которого обмен с диском производится без участия процессора. Стоит отметить, что система запаздывающего кэширования NTFS сможет действовать гораздо более эффективно при наличии Bus Mastering, т.к. NTFS производит отложенную запись гораздо большего числа данных. Системы без Bus Mastering в настоящее время встречаются достаточно редко (обычно это накопители или контроллеры, работающие в режиме PIO3 или PIO4), и если вы работаете с таким диском - то, скорее всего, NTFS потеряет еще пару очков быстродействия, особенно при операциях модификации каталогов (например, активная работа в интернете - работа с кэшем интернета).
Кэширование как чтения, так и записи на уровне жестких дисков (объем буфера HDD - от 128 Кбайт до 1-2 Мбайт в современных дорогих дисках) - фактор, который будет более полезен системам на основе FAT. NTFS из соображений надежности хранения информации осуществляет модификацию системных областей с флагом "не кэшировать запись", поэтому быстродействие системы NTFS слабо зависит от возможности кэширования самого HDD. Системы FAT, напротив, получат некоторый плюс от кэширования записи на физическом уровне. Стоит отметить, что, вообще говоря, всерьез принимать в расчет размер буфера HDD при оценке быстродействия тех или иных файловых систем не стоит.
Подводя краткий итог влиянию быстродействия диска и контроллера на быстродействия системы в целом, можно сказать так: NTFS страдает от медленных дисков гораздо сильнее, чем FAT.
Размер кластера
Хотелось бы сказать пару слов о размере кластера - тот параметр, который в файловых системах FAT32 и NTFS можно задавать при форматировании практически произвольно. Прежде всего, надо сказать, что больший размер кластера - это практически всегда большее быстродействие. Размер кластера на томе NTFS, однако, имеет меньшее влияние на быстродействие, чем размер кластера для системы FAT32.
Типичный размер кластера для NTFS - 4 Кбайта. Стоит отметить, что при большем размере кластера отключается встроенная в файловую систему возможность сжатия индивидуальных файлов, а также перестает работать стандартный API дефрагментации - т.е. подавляющее число дефрагментаторов, в том числе встроенный в Windows 2000, будут неспособны дефрагментировать этот диск. SpeedDisk, впрочем, сможет - он работает без использования данного API. Оптимальным с точки зрения быстродействия, по крайней мере, для средних и больших файлов, считается (самой Microsoft) размер 16 Кбайт. Увеличивать размер далее неразумно из-за слишком больших расходов на неэффективность хранения данных и из-за мизерного дальнейшего увеличения быстродействия. Если вы хотите повысить быстродействие NTFS ценой потери возможности сжатия - задумайтесь о форматировании диска с размером кластера, большим чем 4 Кбайта. Но имейте в виду, что это даст довольно скромный прирост быстродействия, который часто не стоит даже уменьшения эффективности размещения файлов на диске.
Быстродействие системы FAT32, напротив, можно довольно существенно повысить, увеличив размер кластера. Если в NTFS размер кластера почти не влияет на размер и характер данных системных областей, то в системе FAT увеличивая кластер в два раза, мы сокращаем область FAT в те же два раза. Вспомните, что в типичной системе FAT32 эта очень важная для быстродействия область занимает несколько Мбайт. Сокращение области FAT в несколько раз даст заметное увеличение быстродействия, так как объем системных данных файловой системы сильно сократиться - уменьшается и время, затрачиваемое на чтение данных о расположении файлов, и объем оперативной памяти, необходимый для буферизирования этой информации. Типичный объем кластера для систем FAT32 составляет тоже 4 Кбайт, и увеличение его до 8 или даже до 16 Кбайт - особенно для больших (десяток и более гигабайт) дисков - достаточно разумный шаг.
Другие соображения
NTFS является достаточно сложной системой, поэтому, в отличие от FAT16 и FAT32, имеются и другие факторы, которые могут привести к существенному замедлению работы NTFS:
Диск NTFS был получен преобразованием раздела FAT16 или FAT32 (команда convert). Данная процедура в большинстве случаев представляет собой тяжелый случай для быстродействия, так как структура служебных областей NTFS, скорее всего, получится очень фрагментированной. Если есть возможность - избегайте преобразования других систем в NTFS, так как это приведет к созданию очень неудачного диска, которому не поможет даже типичный (неспециализированный) дефрагментатор, типа Diskeeper-а или встроенного в Windows 2000.
Активная работа с диском, заполненным более чем на 80% - 90%, представляет собой катастрофический для быстродействия NTFS случай, так как фрагментация файлов и, самое главное, служебных областей, будет расти фантастически быстро. Если ваш диск используется в таком режиме - FAT32 будет более удачным выбором при любых других условиях.
Выводы
В данной заключительной части "одной строчкой" собраны ключевые особенности быстродействия этих трех файловых систем.
FAT - плюсы:
Для эффективной работы требуется немного оперативной памяти.
Быстрая работа с малыми и средними каталогами.
Диск совершает в среднем меньшее количество движений головок (в сравнении с NTFS).
Эффективная работа на медленных дисках.
FAT - минусы:
Катастрофическая потеря быстродействия с увеличением фрагментации, особенно для больших дисков (только FAT32).
Сложности с произвольным доступом к большим (скажем, 10% и более от размера диска) файлам.
Очень медленная работа с каталогами, содержащими большое количество файлов.
NTFS - плюсы:
Фрагментация файлов не имеет практически никаких последствий для самой файловой системы - работа фрагментированной системы ухудшается только с точки зрения доступа к самим данным файлов.
Сложность структуры каталогов и число файлов в одном каталоге также не чинит особых препятствий быстродействию.
Быстрый доступ к произвольному фрагменту файла (например, редактирование больших .wav файлов).
Очень быстрый доступ к маленьким файлам (несколько сотен байт) - весь файл находится в том же месте, где и системные данные (запись MFT).
NTFS - минусы:
Существенные требования к памяти системы (64 Мбайт - абсолютный минимум, лучше - больше).
Медленные диски и контроллеры без Bus Mastering сильно снижают быстродействие NTFS.
Работа с каталогами средних размеров затруднена тем, что они почти всегда фрагментированы.
Диск, долго работающий в заполненном на 80% - 90% состоянии, будет показывать крайне низкое быстродействие.
Хотелось бы еще раз подчеркнуть, что на практике основной фактор, от которого зависит быстродействие файловой системы - это, как ни странно, объем памяти машины. Системы с памятью 64-96 Мбайт - некий рубеж, на котором быстродействие NTFS и FAT32 примерно эквивалентно. Обратите внимание также на сложность организации данных на вашей машине. Если вы не используете ничего, кроме простейших приложений и самой операционной системы - может случиться так, что FAT32 сможет показать более высокое быстродействие и на машинах с большим количеством памяти.
NTFS - система, которая закладывалась на будущее, и это будущее для большинства реальных применений сегодняшнего дня еще, к сожалению, видимо не наступило. На данный момент NTFS обеспечивает стабильное и равнодушное к целому ряду факторов, но, пожалуй, всё же невысокое - на типичной "игровой" домашней системе - быстродействие. Основное преимущество NTFS с точки зрения быстродействия заключается в том, что этой системе безразличны такие параметры, как сложность каталогов (число файлов в одном каталоге), размер диска, фрагментация и т.д. В системах FAT же, напротив, каждый из этих факторов приведет к существенному снижению скорости работы.
Только в сложных высокопроизводительных системах - например, на графических станциях или просто на серьезных офисных компьютерах с тысячами документов, или, тем более, на файл-серверах - преимущества структуры NTFS смогут дать реальный выигрыш быстродействия, который порой заметен невооруженным глазом. Пользователям, не имеющим большие диски, забитые информацией, и не пользующимся сложными программами, не стоит ждать от NTFS чудес скорости - с точки зрения быстродействия на простых домашних системах гораздо лучше покажет себя FAT32.
Какие жесткие диски лучше установить на компьютере с windows 2000/XP: ata (иначе ide) или scsi? Спор о сравнительных достоинствах и недостатках дисков ata и scsi – один из самых давних в отрасли. В одной из статей я уже сравнивал технические характеристики различных вариантов этих технологий и рассказывал, как их использовать в системах на базе windows nt.
За последнее время появились новые реализации интерфейсов ata и scsi. Сфера scsi расширилась и теперь охватывает ultra2 scsi, волоконно-оптический канал, ultra160 scsi и новейший стандарт – ultra320 scsi. Максимальная пропускная способность этих устройств составляет 80, 100, 160 и 320 Мбайт/с, соответственно. Однако высокая скорость всегда была достоинством scsi, поэтому более важным событием стало сокращение ценового разрыва между технологией scsi и ее конкурентами.
ATA догоняет
Последние стандарты ata 66 (или ultra dma/66, или udma/66) и ata 100 (или ultra dma/100, или udma/100) обеспечивают быструю передачу данных в пакетном и непрерывном режимах (66 и 100 Мбайт/с, соответственно). Планка производительности ata поднимется еще выше с появлением в 2002 г. стандарта se-rialata (первые устройства будут обеспечивать скорость передачи данных 150 Мбайт/с, а в дальнейшем – до 300 и даже 600 Мбайт/с). Таким образом, ata уже годится не только для пользовательских систем и корпоративных настольных компьютеров начального уровня, но и для машин, к дисковой подсистеме которых предъявляются повышенные требования.
Реально на офисных однодисковых системах обычно не удается достигнуть максимального быстродействия. Системные ограничения (например, возможности микросхем ata, архитектура системной шины, физические ограничения диска) часто снижают скорость пересылки данных. Тем не менее, в основном из-за дороговизны scsi (которая объясняется высокой стоимостью контроллера и диска), ata преобладает везде, кроме настольных рабочих станций самого высокого уровня. Однако, чтобы добиться максимальной производительности дисков ata на компьютерах win-dows 2000, недостаточно просто установить новые накопители и подключить кабели.
Стараясь идти в ногу с технологией ata, разработчики microsoft дополнили windows 2000 новыми возможностями и уделяют ata больше внимания при подготовке различных пакетов исправления и программных заплаток. Чтобы эффективно использовать устройства ata на компьютерах windows 2000, требуется иметь базовые знания об интерфейсе ata, необходимых аппаратных средствах и программном обеспечении (например, пакетах исправления и заплатках windows 2000, встроенных драйверах и драйверах независимых поставщиков).
Аппаратные средства
Во-первых, в системе должен быть установлен контроллер, который поддерживает скоростные режимы ata. Самые распространенные стандарты современных дисков – ata/33 (ultra dma/33 или udma/33), ata/66 и ata/100. Практически все контроллеры ata обратно совместимы с дисками прежних стандартов. Например, контроллер ata/100 обычно совместим с дисками ata/33 и даже старыми стандартами ide и eide.
В большинстве систем контроллер реализован в микросхемах ata на системной плате (львиная доля рынка микросхем ata принадлежит компании intel, но есть и другие поставщики, такие, как viahardware.com). Однако в некоторых случаях контроллер может быть размещен на плате расширения pci, например в raid-контроллере ata.
От набора микросхем (важнейшего компонента системной конфигурации ata) и его драйверов зависят функциональные возможности дисков и других устройств, подключенных к контроллеру. Поэтому в первую очередь необходимо тщательно изучить набор микросхем на системной или вспомогательной плате и определить его возможности. Эту информацию можно получить у поставщика ком-пьютера, с системной платы или платы контроллера.
Если микросхемы ata расположены на системной плате, необходимо убедиться, что bios системы поддерживает нужные режимы ata. По всей вероятности, конкретный режим ata реализован в наборе микросхем, но он может отсутствовать в редакции bios, регулярно обновляемой поставщиками ПК и системных микросхем. В этом случае новую версию bios можно получить на web-сайте изготовителя системной платы или компьютера.
Затем следует убедиться, что аппаратные средства обеспечивают нужный режим ata и настроены на оптимальную производительность. Во-первых, все жесткие диски должны поддерживать необходимые режимы ata (например, ata/66, ata/100). Во-вторых, важно распределить диски по отдельным каналам, так как по умолчанию канал ata работает со скоростью самого медленного диска. Если диски ata/33 и ata/100 установлены в одном канале, то скорость передачи данных будет определяться быстродействием ata/33. Поэтому следует разместить медленные устройства ata (например, устройства cd-rom, cd-r, cd-rw, zip, старые жесткие диски) на одном канале, а скоростные жесткие диски – на другом.
Кроме того, необходимо верно выбрать кабели. В спецификациях ata/33, ata/66 и ata/100 указывается, что устройства следует подключать через специальный 80-жильный ленточный кабель, а не 40-жильные кабели, применявшиеся в прежних дисках ata. Дополнительные жилы кабеля нужны для заземления и увеличивают соотношение сигнал/шум при передаче данных. И наконец, накопители следует подключать к 80-жильному кабелю иначе, чем к прежним 40-жильным кабелям. Главное устройство (drive 0) необходимо разместить на конце 80-жильного кабеля, а вторичный накопитель (drive 1) нужно подключить к среднему разъему. Синий разъем на одном конце предназначен для системной платы или платы контроллера, серый разъем в середине – для вторичного устройства, а черный разъем на другом конце – для главного устройства.
Жесткие диски (винчестеры), как электромеханические устройства, являются одним из самых ненадежных компонентов современного компьютера. Несмотря на то, что в большинстве случаев срок службы последних соизмерим, и даже превосходит время их эксплуатации до момента морального устаревания и замены более новыми моделями, все же отдельные экземпляры выходят из строя в течение первых месяцев эксплуатации. Выход жесткого диска из строя - самое худшее, что может случиться с вашим компьютером, так как при этом часто необратимо теряются накопленные на нем данные. Если резервная копия по какой-то причине отсутствует, то суммарный ущерб от поломки заметно превышает номинальную стоимость современных винчестеров.
Многие фирмы, пользуясь ситуацией, предлагают свои услуги по восстановлению информации с вышедшего из строя накопителя. Очевидно, это обходится недешево и целесообразно только тогда, когда на диске находилось что-то действительно ценное. В противном случае легче просто смириться с потерей.
Ремонт жестких дисков требует специального оборудования и практически невозможен в домашних условиях. Так, например, для вскрытия контейнера необходима особо чистая от пыли комната. Казалось бы, положение безнадежно и нечего даже помышлять о восстановлении поломанного диска в домашних условиях. Но, к счастью, не все поломки настолько серьезны, и во многих случаях можно обойтись для ремонта подручными (а иногда чисто программными) средствами.
Один из самых частых отказов винчестеров фирмы western digital (а также и некоторых других) выглядит следующим образом: жесткий диск не опознается bios, а головки при этом отчетливо стучат. Скорее всего, по какой-то причине не работает блок термокалибровки, и устройство не может обеспечить нужный зазор между головкой и рабочей поверхностью "блина". Обычно это происходит при отклонении от нормального температурного режима эксплуатации, например, в зимнее время, когда жесткие диски в плохо отапливаемых помещениях "выстывают" за ночь (при температуре 18...210С жесткий диск часто может исправно функционировать и с испорченным механизмом термокалибровки). Попробуйте дать поработать винчестеру в течение нескольких часов, чтобы он прогрелся, при этом рано или поздно винчестер попадает в необходимый диапазон температур и работоспособность (возможно, временно) восстанавливается. Разумеется, первым делом нужно скопировать всю информацию, поскольку работоспособность такого диска уже не гарантируется. То же можно рекомендовать и в отношении устаревших моделей без термокалибровки; часто они оказываются зависимыми от температурного режима, и с ростом износа винчестера эта зависимость проявляется все сильнее.
Вторым по распространенности отказом является выход из строя модуля диагностики при полной исправности остальных компонентов. Как это ни покажется парадоксальным, но полностью рабочий винчестер не проходит диагностику. При этом в регистре ошибок (порт ox1f1 для первого жесткого диска) могут содержаться значения, приведенные ниже:
Диагностические ошибки
Бит Содержимое Источник ошибки
7 0 Ошибка master диска
1 Ошибка slave диска
2-0 011 Ошибка секторного буфера
100 Ошибка контрогльной суммы, не устранимая избыточным кодированием
101 Ошибка микроконтроллера
Разные biosы могут различно реагировать на такую ситуацию, но все варианты сводятся к одному - жесткий диск не определяется и не "чувствуется". Однако на уровне портов ввода/вывода устройство функционирует отлично. Заметим, что существуют такие материнские платы (особенно среди новых моделей), которые, обнаружив ошибку микроконтроллера винчестера, просто отключают питание жесткого диска. Несложно написать для испорченного таким образом винчестера драйвер, который обеспечит работу с диском через высокоуровневый интерфейс int 0x13. Например, следующая процедура обеспечивает посекторное чтение и запись через порты ввода/вывода для первого жесткого диска в chs режиме.
lba mode для упрощения понимания не поддерживается. Необходимую техническую информацию обычно можно найти на сайте производителя вашего жесткого диска.
Этот фрагмент может служить вполне работоспособным ядром для драйвера 16-ти разрядного режима. Для упрощения понимания не включена задержка после каждого обращения к порту. В зависимости от соотношений скорости вашего процессора и контроллера диска эта задержка может и не потребоваться (в противном случае рекомендуется читать регистр статуса ox1f7, дожидаясь готовности контроллера). При этом не следует спешить с заменой такого жесткого диска на новый, с подобной неисправностью можно успешно работать не год и не два. Последнее, правда, лишь при условии, что все используемое программное обеспечение не будет конфликтовать с нестандартным драйвером. Писать драйвер, скорее всего, придется вам самому, поскольку не известно ни одной коммерческой разработки в этом направлении, а все любительские разработки выполнены в основном "под себя". Так, например, драйвер от kpnc hddfix3a поддерживает только винчестеры primary master до пятисот мегабайт и не работает в среде windows 95 (разработан на год раньше ее появления).
Более легкий, но не всегда осуществимый путь - запретить тестирование жестких дисков biosом или, по крайней мере, игнорировать результаты такового. Как это осуществить, можно прочесть в руководстве на материнскую плату (или обратиться за помощью к службе технической поддержки фирмы-производителя, поскольку в руководствах пользователя такие тонкости нередко опускают). Например, попробуйте установить "halt on" в "never" или перезаписать flach bios, модифицировав его так, чтобы тот не выполнял подобную проверку. Если Вам повезет, жесткий диск заработает! Однако иногда все же происходят и аппаратные отказы. Например, у винчестеров фирм samsung и conner отмечены случаи отказа модуля трансляции мультисекторного чтения/записи. Если это не будет обнаружено внутренним тестом устройства, то такой жесткий диск вызовет зависание операционной системы на стадии ее загрузки. Для предотвращения этого достаточно добавить в config.sys ключ multi-track=off и отключить аналогичные опции в blose. При этом, проиграв в скорости, все же можно заставить жесткий диск сносно работать. Понятно, что эксплуатировать восстановленный таким образом диск длительное время нерационально по причине потери быстродействия. Лучше приобрести новый, на который и скопировать всю информацию. С другой стороны, такой жесткий диск все же остается полностью рабочим и успешно может служить, например, в качестве резервного.
На том же connere эпизодически выходит из строя блок управления позиционированием головок, так что последние уже не могут удержаться на дорожке и при обращении к следующему сектору немного "уползают". При этом считывание на выходе дает ошибочную информацию, а запись необратимо затирает соседние сектора. Бороться с этим можно позиционированием головки перед каждой операцией записи/чтения, обрабатывая за один проход не более сектора. Понятно, что для этого необходимо вновь садиться за написание собственного драйвера. К счастью, он достаточно простой (можно использовать аппаратное прерывание от жесткого диска int 0x76 irq14, вставив в тело обработчика команду сброса контроллера. В данном случае подразумевается, что контроллер используемого жесткого диска проводит рекалибровку головки во время операции сброса. Некоторые модели этого не делают. В этом случае придется прибегнуть к операции позиционирования головки (функция ОхС дискового сервиса 0x13). Первые модели от вторых можно отличить временем, требуемым на сброс контроллера. Понятно, что электроника "сбрасывается" мгновенно, а позиционирование головки требует хоть и не большого, но все же заметного времени. Современные модели с поддержкой кэширования этого часто не делают или "откладывают" операции с головкой до первого к ней обращения. Разумеется, в этом случае кэширование придется выключить. Большинство bios позволяет это делать без труда, и нет нужды программировать контроллер самостоятельно. В другом случае вышедший из строя блок позиционирования (трансляции) подводит головки вовсе не к тому сектору, который запрашивался. Например, головки могли физически сместиться с оси, "уползая" в сторону. Разумеется, этот дефект можно скорректировать программно, достаточно проанализировать ситуацию и логику искажения трансляции. Многие модели позиционируют головку, используя разметку диска, что страхует от подобных поломок (к сожалению, сейчас от такого подхода большинство фирм отказались, выигрывая в скорости).
Конечно, все описанные программные подходы в действительности не устраняют неисправность, а только позволяют скопировать с казалось бы уже нерабочего винчестера ценные и еще не сохраненные данные. При этом ни к чему писать универсальный драйвер для win32 и защищенного режима. Вполне можно ограничиться dos-режимом. Для копирования файлов последнего должно оказаться вполне достаточно, конечно за исключением тех случаев, когда диск был отформатирован под ntsf или другую, не поддерживаемую ms-dos, систему. К счастью, для многих из них есть драйверы, которые позволяют "видеть" подобные разделы даже из "голой" ms-dos. В крайнем случае, можно ограничиться посекторным копированием на винчестер точно такой же топологии. При этом совершенно не имеет значения используемая файловая система и установленная операционная система.
Посекторно скопировать диск на винчестер с иной топологией трудно, но возможно. Дело в том, что многие современные контроллеры жестких дисков позволяют пользователю менять трансляцию произвольным образом. Для этого необходимо приобрести винчестер, поддерживающий lba-режим (а какой из современных жестких дисков его не поддерживает?). При этом он может быть даже большего объема, нежели исходный, но это никак не помешает копированию. Другой вопрос, что без переразбиения скопированный таким образом диск не "почувствует" дополнительных дорожек и следует запустить norton disk doctor, который устранит эту проблему.
Достаточно часто нарушается вычисление зон предком-пенсации. Дело в том, что плотность записи на разных цилиндрах не одинакова, так как линейная скорость растет от центра диска к периферии. Разумеется, гораздо легче постепенно уплотнять записи, нежели искать некий усредненный компромисс. На всех существующих моделях плотность записи изменяется скачкообразно и на последних моделях программно доступна через соответствующие регистры контроллера. При этом значения, выставленные в bios, практически любой жесткий диск (с интерфейсом ide) просто игнорирует. Предыдущие модели не имели с этим проблем, и только винчестеры, выпущенные в течение последних двух лет, склонны к подобным поломкам. Скорее, даже не к поломкам, а к сбоям, в результате которых искажается хранимая где-то в недрах жесткого диска информация. Если контроллер позволяет ее программно корректировать, то считайте, что ваш жесткий диск спасен. Конечно, придется пройти сквозь мучительные попытки угадать оригинальные значения, однако это можно делать и автоматическим перебором до тех пор, пока винчестер не начнет без ошибок читать очередную зону. Помните, что любая запись на диск способна нарушить низкоуровневую разметку винчестера, после чего последний восстановлению не подлежит и его останется только выкинуть. Производите только чтение секторов!
Если же контроллер не позволяет программно управлять предкомпенсацией, то еще не все потеряно. Попробуйте перед каждым обращением делать сброс контроллера, а точнее, его рекалибровку (команда ixh). В некоторых случаях это срабатывает, поскольку с целью оптимизации скорости обмена предкомпенсацией обычно управляет не один блок. И, кроме того, иногда контроллер кэша не учитывает предкомпенсацию, а его сброс реализует последнюю аппаратно. К сожалению, это по большей части догадки и результаты экспериментов автора, так как техническая документация фирм-производителей по этому поводу не отличается полнотой, а местами содержит противоречия. Можно испытать и другой способ - попробовать перезаписать микрокод контроллера (команда 92h). Конечно, это доступно только для специалистов очень высокого класса, но ведь доступно! Заметим, что не все контроллеры поддерживают такую операцию. С другой стороны, это и хорошо, так как уменьшает вероятность сбоя и не дает некорректно работающим программам (вирусам в том числе) испортить дорогое устройство. Жесткие диски от samsung обладают еще одной неприятной особенностью - часто при подключении шлейфа "на лету", при включенном питании, они перестают работать. Внешне это выглядит так: индикатор обращения к диску постоянно горит, но диск даже не определяется biosom, или определяется, но все равно не работает. Близкое рассмотрение показывает, что на шине пропадает сигнал готовности устройства. В остальном контроллер остается неповрежденным. Разумеется, если не обращать внимание на отсутствие сигнала готовности, то с устройством можно общаться, делая вручную необходимые задержки (поскольку физическую готовность устройства уже узнать не представляется возможным, приходится делать задержки с изрядным запасом времени). При этом, к сожалению, придется отказаться от dma-mode (а уж тем более ultra-dma) и ограничиться pio 1 (с небольшим риском - pio 2) режимом. Конечно, писать соответствующий драйвер вам придется опять самостоятельно. Разумеется, скорость обмена в режиме pio 1 по сегодняшним меркам совершенно неудовлетворительна и не годится ни для чего другого, кроме как копирования информации со старого на новый винчестер, но некоторые "нечистоплотные" продавцы компьютерной техники как-то ухитряются устанавливать подобные экземпляры на продаваемые машины. Будьте осторожны! Учитывая, что написание подобных драйверов для win32 - трудоемкое занятие, большинство ограничивается поддержкой одной лишь ms-dos, и вовсе не факт, что компьютер, демонстрирующий загрузку win95, содержит исправный, а не реанимированный подобным образом жесткий диск.
У жестких дисков фирмы samsung при подключении "налету" может появляться другой неприятный дефект - при запросах на чтение контроллер периодически "повисает" и не завершает операцию. В результате "замирает" вся операционная система (впрочем, windows nt с этим справляется, но, вероятно, не всегда). На первый взгляд может показаться, что с этого винчестера несложно скопировать ценные файлы, но при попытке выполнить это выясняется, что диск "зависает" все чаще и чаще и копирование растягивается до бесконечности. Однако если выполнить сброс контроллера, то можно будет повторить операцию. Это можно сделать аппарат -но, подпаяв одну кнопку на линию сброса и статуса. Последнее нужно для указания на ошибочную ситуацию, чтобы операционная система повторила незавершенную операцию. Если этого не сделать, то часть секторов не будет реально прочитана (записана). Или можно выполнять сброс автоматически, например, по таймеру. Чтобы не сталкиваться с подобной ситуацией, никогда не следует подсоединять/отсоединять винчестер при включенном питании. Очень часто это приводит к подобным ошибкам, хотя производители других фирм, по-видимому, как-то от этого все же защищаются, ибо аналогичной ситуации у них практически не встречается. Все же не стоит искушать судьбу... От аппаратных ошибок теперь перейдем к дефектам поверхности. Заметим сразу, что последнее встречается гораздо чаще и проявляется намного коварнее. Обычно это ситуация, в которой мало что можно предпринять. Но достичь главной цели - спасти как можно больше уцелевших данных - довольно часто удается. Возьмем такую типичную ситуацию как ошибка чтения сектора. Маловероятно, чтобы сектор был разрушен целиком. Чаще всего "сыплется" только какая-то его часть, а все остальные данные остаются неискаженными. Существуют контроллеры двух типов. Первые, обнаружив расхождение контрольной суммы считанного сектора, все же оставляют прочитанные данные в буфере и позволяют их извлечь оттуда, проигнорировав ошибку чтения. Вторые либо очищают буфер, либо просто не сбрасывают внутренний кэш, в результате чего все равно прочитать буфер невозможно. На практике обычно встречаются последние. При этом сброс кэша можно инициировать серией запросов без считывания полученных данных. Кэш при этом переполняется, и наиболее старые данные будут вытолкнуты в буфер. Остается их только прочесть. Конечно,-это крайне медленно, но, к сожалению, универсальной команды сброса кэша не существует. Разные разработчики реализуют это по-своему (впрочем, иногда это можно найти в документации на чипы, используемые в контроллере). western digital сообщает в техническом руководстве что при длинном чтении сектора без повтора контроль сектора не выполняется и он будет-таки целиком помещен в буфер. Кстати, так и должно быть по стандарту. Увы, остальные фирмы от него часто отклоняются по разным соображениям. Остается определить, какие же из прочитанных данных достоверные, а какие нет (если этого не видно "визуально" - например, в случае текстового или графического файлов)? Разумеется, в подобных рамках задача кажется неразрешимой, но это не совсем так. Дело в том, что можно произвести не только короткое, но и длинное чтение (ox22h req ploin long with retry), для чего можно использовать следующую процедуру. При этом кроме собственно данных читаются также и корректирующие коды. Автоматическая коррекция не выполняется (хотя некоторые контроллеры это реализуют аппаратно и не могут отключить автокоррекцию; в документации этот момент, кстати, не уточняется). Как правило, используются корректирующие коды Рида-Соломона, хотя последнее не обязательно. Математические законы позволяют не только определить место возникновения сбоя, но и даже восстановить несколько бит. При больших разрушениях можно определить только место сбоя, но достоверно восстановить информацию не удается.
Модуляция при записи такова, что все биты, стоящие справа от сбойного, уже не достоверны. Точнее, не все, а только в пределах одного пакета. Обычно за один раз записывается от 3 до 9 бит (необходимо уточнить у конкретного производителя) и содержимое остальных пакетов, как правило, остается достоверным. Самое интересное, что зачастую сбойный пакет можно восстановить методом перебора! При этом можно даже рассчитать, сколько вариантов должно получиться. Учитывая хорошую степень "рассеяния" корректирующих кодов можно сказать, что не очень много. И таким образом можно восстановить казалось бы безнадежно испорченные сектора, а вместе с ними и файлы, расположенные "поверх" последних.
Выше были перечислены наиболее типичные случаи отказов жестких дисков, которые поддавались чисто программному восстановлению если уж не винчестера, то хотя бы хранимых на нем данных. Разумеется, что иногда жесткий диск выходит из строя полностью (например, при неправильно подключенном питании, скачках напряжения) от вибрации или ударов, а то и просто из-за откровенного заводского брака. Есть один старый проверенный способ - найти жесткий диск такой же точно модели и заменить электронную плату. К сожалению, последнее из-за ряда конструктивных особенностей все реже и реже бывает возможно, а уж дефекты поверхности этот способ и вовсе бессилен вылечить. Поэтому, берегите свой жесткий диск и почаще проводите резервное копирование. Помните, что самое дорогое это не компьютер, а хранимая на нем информация!
Эта статья является продолжением статьи о создании счетчика просмотров для каждой страницы сайта на php и MySQL (если Вы ее не читали, то обязательно прочтите, иначе ничего не поймете из ниже сказанного). В этой статья я решил продолжить тему и расширить возможности счетчика просмотров страниц.
Для увеличения возможностей и получения статистики просмотров страниц сайта к базовому php скрипту необходимо добавить несколько строк и своих функций. В частности нужно будет создать еще одну таблицу, которая имеет следующую структуру:
Как видно из структуры MySQL таблицы, она состоит всего из двух полей (page_id – хэш сумма md5() от urla страницы и page_url – url страницы) и индекса, установленного на поле page_id – для значительного ускорения поиска значения в таблице. И еще, я не стал изменять изначальную таблицу my_log, которая использовалась для подсчета количества просмотров страниц, а создал другую по одной простой, но очень весомой причине: чем больше данных в таблице – тем медленнее осуществляется поиск по таблице. А скорость работы php скриптов такого уровня не должна ощутимо влиять на работу сайта в целом. Ведь если у вас коммерческий и при этом очень посещаемый сайт, то тратить строго ограниченное процессорное время на второстепенные задачи просто невыгодно, ведь зачастую прибыль зависит от того, сколько человек сможет увидеть ваш сайт.
Теперь перейдем непосредственно к коду php скрипта. Я внес в него незначительные изменения, в основном это новые функции для работы с MySQL таблицей my_log_urls.
В counter.php внес следующие изменения:
добавляем функцию Default_Write_URL
В результате, получаем значительную экономию времени т.к. делаем всего одну запись в таблицу my_log_urls и одну в my_log, и при следующих запросах этой же страницы запрос к таблице my_log_urls выполняться не будет, т.к. запись уже существует в таблице my_log, следовательно и в таблице my_log_urls она то же есть.
Для подсчета рейтинга страниц сайта, предлагаю написать другой php скрипт, который будет по значениям просмотров страницы в таблице my_log брать значения в таблице my_log_urls. А результат представлять в виде таблицы с данными о просмотрах страниц, отсортированными по убыванию (от большего значения к меньшему).
Ниже приведен код php скрипта, который необходимо скопировать в созданный вами файл top.php:
Данный php скрипт выводит 10 самых популярных страниц вашего сайта за последние сутки и за все время. В принципе, можно осуществлять вывод и большего числа страниц, изменив в php функциях MySQLReadAll и MySQLReadToday лимит считываемых из таблицы записей. А так же можно вместо самых популярных страниц увидеть самые непопулярные, изменив способ сортировки в этих же функциях с DESC на ASC.
Скачать данный php скрипт, вместе с модифицированным php скриптом подсчета просмотров страниц, можно по этой ссылке.
Потоки всегда создаются в контексте какого-либо процесса, и вся их жизнь проходит только в его границах. На практике это означает, что потоки исполняют код и манипулируют данными в адресном пространстве процесса. Если два или более потока выполняются внутри одного процесса, они делят одно адресное пространство.
Любой поток (thread) состоит из двух компонентов:
объекта ядра, через который ОС управляет потоком. Там же хранится статистическая информация о потоке.
Стека потока, который содержит параметры всех функций и локальные переменные, необходимые потоку для выполнения кода.
Потоки могут выполнять один и тот же код, манипулировать одними и теми же данными, а также совместно использовать описатели объектов ядра, поскольку таблица описателей создается не в отдельных потоках, а в процессах.
Потоки используют намного меньше ресурсов системы, чем процессы, поэтому все задачи, требующие параллельного выполнения нескольких подзадач, стоит решать по возможности с помощью потоков, не прибегая к созданию нескольких процессов.
Обычная структура многопоточного приложения рассчитана на одновременное исполнение нескольких подзадач. Однако стоит помнить, что, создавая многопоточное приложение, нам придется заботиться о сохранности и ликвидности, общих для всех потоков, данных.
Создание потока.
Первичный поток, который присутствует в программе, начинает свое выполнение с главной функции потока типа WinMain.
Для создания вторичного потока необходимо создать и для него входную функцию, которая выглядит примерно так:
Имя у функции вторичного потока, в отличии от первичного, может быть любым однако, при наличии нескольких разных потоков, назвать функции необходимо по-разному, иначе система создаст разные реализации одной и той же функции.
Когда поток закончит свое исполнение, он вернет управление системе, память, отведенная под его стек, будет освобождена, а счетчик пользователей его объекта ядра "поток" уменьшится на 1. Когда счетчик обнулится, этот объект ядра будет разрушен.
Для создания своего потока необходимо использовать функцию CreateThread:
При каждом вызове этой функции система создает объект ядра (поток). Это не сам поток, а компактная структура данных, которая используется операционной системой для управления потоком и хранит статистическую информацию о потоке.
Система выделяет память под стек потока из адресного пространства процесса. Новый поток выполняется в контексте того же процесса, что и родительский поток. Поэтому он получает доступ ко всем описателям объектов ядра, всей памяти и стекам всех потоков в процессе. За счет этого потоки в рамках одного процесса могут легко взаимодействовать друг с другом.
CreateThread - это Windows-функция, создающая поток. Если вы пишете код на С/С++ не вызывайте ее. Вместо нее Вы должны использовать _beginthreadex из библиотеки Visual C++. Почему это так важно в наших следующих выпусках.
Параметры функции CreateThread.
LpThreadAttributes - является указателем на структуру LPSECURITY_ATTRIBUTES. Для присвоения атрибутов защиты по умолчанию, передавайте в этом параметре NULL.
DwStackSize - параметр определяет размер стека, выделяемый для потока из общего адресного пространства процесса. При передаче 0 - размер устанавливается в значение по умолчанию.
LpStartAddress - указатель на адрес входной функции потока.
LpParameter - параметр, который будет передан внутрь функции потока.
DwCreationFlags - принимает одно из двух значений: 0 - исполнение начинается немедленно, или CREATE_SUSPENDED - исполнение приостанавливается до последующих указаний.
LpThreadId - Адрес переменной типа DWORD в который функция возвращает идентификатор, приписанный системой новому потоку.
Завершение потока
Поток можно завершит четырьмя способами:
функция потока возвращает управление (рекомендуемо);
поток самоуничтожается вызовом функции ExitThread;
другой поток процесса вызывает функцию TerminateThread;
завершается процесс, содержащий данный поток.
Все способы , за исключением рекомендуемого, являются нежелательными и должны использоваться только в форс-мажорных обстоятельствах.
Функция потока, возвращая управление, гарантирует корректную очистку всех ресурсов, принадлежащих данному потоку. При этом:
любые С++ объекты, созданные данным потоком, уничтожаются соответствующими деструкторами;
система корректно освобождает память, которую занимал стек потока;
система устанавливает код завершения данного потока. Его функция и возвращает;
счетчик пользователей данного объекта ядра (поток) уменьшается на 1.
При желании немедленно завершить поток изнутри используют функцию ExitThread(DWORD dwExitCode).
При этом освобождаются все ресурсы ОС, выделенные данному потоку, но С С++ ресурсы (например, объекты классов С++) не очищаются. Именно поэтому не рекомендовано завершать поток, используя эту функцию.
Если же вы ее использовали, то кодом возврата потока будет тот параметр, который вы передадите в данную функцию.
Как и для CreateThread для библиотеки Visual C++ существует ее аналог _endthreadex, который и стоит использовать. Об причинах в следующем выпуске.
Если появилась необходимость уничтожить поток снаружи, то это моет сделать функция TeminateThread.
Эта функция уменьшит счетчик пользователей объекта ядра (поток) на 1, однако при этом не разрушит и не очистит стек потока. Стек будет существовать, пока не завершится процесс, которому принадлежит поток. При задачах, постоянно создающих и уничтожающих потоки, это приводит к потере памяти внутри процесса.
При завершении процесса происходит следующее.
Завершение потока происходит принудительно. Деструкторы объектов не вызываются, и т.д. и т.д.
При завершении потока по такой причине, связанный с ним объект ядра (поток) не освобождается до тех пор, пока не будут закрыты все внешние ссылки на этот объект.
Изменяя аргумент iAngle, можно вращать начальную точку - центр. А изменяя iSector можно выводить текст как по окружности, так и по дуге (она задается в градусах). Наверняка многие видели такой эффектик. Какой-нибудь текст крутится вокруг центра и меняется его радиус - расстояние от центра до букв. И тут можно такое же сделать. Для этого надо вызывать эту процедуру по таймеру, где перед вызовом изменять iAngle и iR (переменные завести). Только перед каждым рисованием, надо в этой функции очищать уже нарисованное, чтобы не оставалось старого. А если это непосредственно на канве делается медленно и мигает, но надо рисовать на битмапе и оттуда изображение копировать.
Давайте определимся с номенклатурой. Поле - это ячейка в таблице. Запись - набор из полей. Так вот, существуют разные типы полей - обычные, индексные и ключевые. Обычные поля - просто данные. Индексное поле - поле, по которому данные сортируются. Ключевое - поле, значение которого уникально. В общем-то четкого разделения нет. Ведь программа базы данных может сортировать таблицу и по обычным полям, а индексное поле может быть также уникальным.
В BDE достаточно логично поределена структура построения полей и их типов. Для этого имеются классы TxxxDef (три икса здесь обозначают подстановку, а то мало ли что Вы подумаете ;)), произведенные ото абстрактного базового класса TNamedItem. В компоненте TTable имеются и соответствующие свойства
TIndexDefs
TFieldDefs
Как и следовало предполагать, эти свойства содержат в себе определения индексных и обычных полей. Здесь нет свойства типа TKeyDefs, потому что в таблицах типа Парадокс индексные поля могут быть сами по себе уникальны. За счет этих свойств и задаются параметры таблицы, ее сетка. Создание таблицы довершает метод CreateTable.
Теории было много, теперь практика. Вот пример, честно скажу, взятый их Хелпа и перекомментированный автором (то есть мной).
Это все еще объяснять и объяснять. Но, я надеюсь, общая логика понятна.
Такие типы данных, как int, float, char и long, являются неотъемлемой частью C/C++ и вам не нужно писать никакого кода, чтобы сообщить компилятору о том, что означают эти слова. C/C++ позволяет вам также объ-являть свои собственные, специальные типы данных. В следующем разделе вы узнаете, как объявлять структуры, которые можно отнести к специальным типам данных.
Как вы уже знаете, переменная в C/C++ объявляется следующим образом:
В приведенном операторе iMyVariable объявлена как целая переменная. А вот объявление переменной типа char:
Напишите следующий исходный код:
В коде, который вы написали, имеются два оператора #include:
Файл iostream.h включен в код, поскольку в main(void) используется cout. Файл string.h включается потому, что в main(void) используется функция strcpy() (объявленная в файле string.h). Затем вы объявляете структуру:
Обратите внимание на синтаксис объявления структуры. Оно начинается с ключевого слова struct, за которым следует имя типа-структуры. В этой программе типу структуры присвоено имя MYSTRUCTURE. Затем следует собственно определение структуры, заключенное в фигурные скобки. Не забудьте поставить точку с запятой после закрывающей фигурной скобки. Теперь посмотрите на код внутри фигурных скобок:
Это означает, что MYSTRUCTURE состоит из строки с именем sName и целого с именем iAge, sName и iAge называются элементами данных структуры; Вы объявили их "Внутри" cтруктуры MYSTRUCTURE. Код в main(void) объявляет переменную с именем MyStructure типа MYSTRUCTURE:
Вспомните, что в объявляли переменную iNum1 следующим образом:
Когда вы объявляете MyStructure , которая будет структурой типа MYSTRUCTURE, рассматривайте переменную MyStructure аналогично переменной iNum1. MyStructure - это имя переменной, а ее типом является MYSTRUCTURE точно так же, как типом переменной iNum1 является int. (Обратите внимание, что по традиции имя структуры составлено из символов нижнего регистра или в нем смешаны символы нижнего и верхнего регистров, как, например, в имени MyStructure, но в имени типа структуры используются только символы верхнего регистра, как, например, в MYSTRUCTURE.)
Следующий оператор в main(void) копирует строку 'Andy' в элемент данных MyStructure.sName:
В этом операторе обращение к элементу данных sName записано как MyStructure.sName Следующий оператор присваивает значение 13 элементу данных iAge cтруктуры MyStructure: MyStructure.iAge - 13; Затем выполняется ряд операторов вывода cout:
Сложив все вместе, мы видим, что программа MyStruct выводит сообщение My name is Andy and I am 13 years old. (Меня зовут Andy и мне 13 лет)
В состав библиотеки MFC входит ряд классов, представляющих стандартные диалоговые панели. Эти классы позволяют легко реализовать такие часто используемые операции, как открытие и сохранение файла, выбор цвета, выбор шрифта и т.д. Все эти классы наследуются от CCommonDialog, который в свою очередь является производным по отношению к базовому классу CDialog.
Приведем классы стандартных диалоговых панелей и их назначение:
CColorDialog - Панель для выбора цвета
CFileDialog - Панель выбора файлов для открытия и сохранения на диске
CFindReplaceDialog - Панель для выполнения операции поиска и замены
CFontDialog - Панель для выбора шрифта
CPrintDialog - Панель для вывода документа на печать
CPageSetupDialog - Панель выбора формата документа
COleDialog - Панель для управления технологией OLE
Классы, управляющие стандартными диалоговыми панелями, определены в файле afxdlgs.h. Поэтому при использовании этих классов в приложении необходимо включить этот файл в исходный текст при помощи директивы #include.
Панель выбора цвета (класс CColorDialog)
Чтобы отобразить на экране стандартную диалоговую панель выбора цвета, надо создать объект класса CColorDialog, а затем вызвать метод DoModal. При создании объекта класса СColorDialog используется следующий конструктор:
Все параметры конструктора необязательны, однако в некоторых случаях использование этих параметров может помочь.
Первый параметр clrInit позволяет указать цвет, выбранный по умолчанию сразу после открытия диалоговой панели. Если параметр не будет указан, в качестве цвета, выбранного по умолчанию, будет использоваться черный цвет.
Параметр dwFlags содержит набор флагов, управляющих диалоговой панелью выбора цвета. При помощи него блокировать или разрешать работу некоторых элементов управления диалоговой панели выбора цвета. Если при создании объекта класса CColorDialog не указать параметр dwFlags, тем не менее можно выполнить настройку диалоговой панели, обратившись непосредственно к элементу m_cc данного класса. Параметр dwFlags, указанный в конструкторе, используется для инициализации m_cc. Изменения в элемент m_cc должны быть внесены до того, как панель будет отображаться на экране.
Последний параметр pParentWnd можно использовать, чтобы указать родительское окно диалоговой панели.
Методы класса CСolorDialog
Чтобы вывести диалоговую панель выбора цвета на экран, необходимо использовать метод DoModal. После отображения панели на экране пользователь может выбрать из нее цвет и нажать кнопки OK или Cancel для подтверждения выбора цвета или отказа от него. Когда диалоговая панель закрывается, метод DoModal возвращается значения IDOK и IDCANCEL, в зависимости от того, какую кнопку нажал пользователь:
На экране появится стандартная диалоговая панель выбора цвета Color. В верхней половине диалоговой панели расположены 48 прямоугольников, имеющих различные цвета. Они представляют так называемые основные цвета (Basic colors). Можно выбрать один из этих цветов и нажать кнопку OK. После того, как диалоговая панель закрыта (метод DoModal завершил свою работу), можно воспользоваться методами класса CColorDialog, чтобы узнать цвета, выбранные пользователем.
Для определения цвета, выбранного пользователем, можно обратиться к методу GetColor класса CColorDialog. Данный метод возвращает значение COLORREF, соответствующее выбранному цвету.
Если пользователю недостаточно основных цветов, представленных в диалоговой панели Color, он может выбрать до 16 дополнительных цветов. Для этого он должен нажать кнопку DefineCustom Colors. Диалоговая панель изменит свой внешний вид - появятся дополнительные органы управления, позволяющие выбрать любой из 16 777 216 цветов. Когда цвет выбран, нужно нажать кнопку Add Custom Colors. Выбранный цвет будет добавлен к дополнительным цветам (Custom colors) - один из свободных прямоугольников окрасится соответствующим цветом.
При помощи метода GetSavedCustomColors класса CColorDialog можно определить дополнительные цвета, выбранные пользователем в диалоговой панели Color. Этот метод возвращает указатель на массив из 16 элементов типа COLORREF. Каждый элемент массива описывает один дополнительный цвет.
Когда диалоговая панель Color отображается приложением первый раз, все прямоугольники, отображающие дополнительные цвета, имеют белый цвет. Дополнительные цвета, выбранные пользователем, сохраняются во время работы приложения. После перезапуска приложения дополнительные цвета сбрасываются.
Панель выбора файлов (класс CFileDialog)
Среди стандартных диалоговых панелей, для которых в библиотеке MFC создан специальный класс, есть панели для работы с файловой системой - Open и Save As. Диалоговая панель Open позволяет выбрать один или несколько файлов и открыть их для дальнейшего использования. Диалоговая панель Save As позволяет выбрать имя файла для записи в него документа.
Для управления диалоговыми панелями Open и Save As предназначен один класс CFileDialog. Рассмотрим конструктор класса CFileDialog более подробно:
Объекты класса CFileDialog представляют диалоговые панели Open или Save As в зависимости от параметра bOpenFileDialog. Если параметр bOpenFileDialog содержит значение TRUE, то создается объект, управляющий диалоговой панелью Open, а если FALSE - диалоговой панелью Save As.
Параметр bOpenFileDialog является единственным обязательным параметром, который необходимо указать. Остальные параметры конструктора класса CFileDialog задают различные режимы работы панели и могут не указываться.
Чтобы создать объект класса CFileDialog , представляющий диалоговую панель для открытия файлов (mFileOpen), и объект, представляющий диалоговую панель для сохранения файлов (mFileSaveAs), можно воспользоваться следующими вызовами конструктора класса:
Во многих случаях имена файлов, которые нужно открыть или закрыть, имеют определенное расширение. Параметр lpszDefExt позволяет задать расширение файлов, используемое по умолчанию. То есть, если пользователь при определении имени файла не укажет расширение, имени файла автоматически присваивается расширение, принятое по умолчанию. Если при определении свойств диалоговой панели программист присвоит параметру lpszDefExt значение NULL, то расширение файлов должно задаваться пользователем явно.
В некоторых случаях требуется, чтобы диалоговые панели отображались с уже выбранным именем файла. Чтобы указать имя файла, используемое по умолчанию, применяется параметр lpszFileName. Если параметр lpszFileName имеет значение NULL, данная возможность не реализуется.
С помощью флага dwFlags можно изменить внешний вид и некоторые другие характеристики стандартных диалоговых панелей класса CFileDialog. В него можно записать комбинацию флагов, управляющих различными характеристиками этих панелей. Например, флаг OFN_HIDEREADONLY означает, что из диалоговой панели удаляется переключатель "Read Only", а флаг OFN_OVERWRITEPROMPT (используемый для панели Save As) - что необходимо выводить диалоговую панель с предупреждением, если пользователь выбирает для сохранения имя уже существующего файла.
Диалоговые панели выбора файлов обычно имеют список так называемых фильтров, включающих названия типов файлов и расширения имен файлов данного типа. Выбрав фильтр, пользователь указывает, что он желает работать только с файлами определенного типа, имеющими соответствующее расширение. Файлы с другими расширениями в диалоговых панелях не отображаются.
Список фильтров можно указать через параметр lpszFilter. Одновременно можно указать несколько фильтров. Каждый фильтр задается двумя строками - строкой, содержащей имя фильтра, и строкой, в которой перечислены соответствующие ему расширения имен файлов. Если одному типу соответствует несколько расширений, они разделяются символом ;. Строка, содержащая имя фильтра, отделяется от строки с расширениями файлов символом |. Если используется несколько фильтров, то они также отделяются друг от друга символом |. Например, в качестве строки, задающей фильтры, можно использовать строку вида:
Диалоговые панели, представленные объектами класса CFileDialog, могут иметь или не иметь родительского окна. Чтобы указать родительское окно, нужно передать конструктору CFileDialog указатель на него через параметр pParentWnd.
Методы класса CFileDialog
Создание объекта класса CFileDialog еще не вызывает отображения соответствующей диалоговой панели. Для этого необходимо воспользоваться методом DoModal класса CFileDialog.При вызове метода DoModal для ранее созданного объекта класса CFileDialog на экране открывается соответствующая диалоговая панель. После того, как пользователь завершает работу с диалоговой панелью, метод DoModal вернет значение IDOK или IDCANCEL в случае успешного завершения и нуль - в случае возникновения ошибок:
После того, как пользователь закроет диалоговую панель и метод DoModal вернет управление, можно воспользоваться другими методами класса CFileDialog , чтобы определить имена выбранных файлов:
GetPathName - Определяет полный путь файла
GetFileName - Определяет имя выбранного файла
GetFileExt - Определяет расширение имени выбранного файла
GetFileTitle - Позволяет определить заголовок выбранного файла
GetNextPathName - Если диалоговая панель позволяет выбрать сразу несколько файлов, то этот метод можно использовать для определения полного пути следующего из выбранных файлов
GetReadOnlyPref - Позволяет узнать состояние атрибута "только для чтения" (read-only) выбранного файла
GetStartPosition - Возвращает положение первого элемента из списка имен файлов
Наиболее важный метод - GetPathName. Он получает полный путь файла, выбранного из диалоговых панелей Open или Save As. Если диалоговая панель позволяет выбрать сразу несколько файлов, тогда метод GetPathName возвращает массив строк, состоящий из нескольких строк, заканчивающихся двоичным нулем. Первая из данных строк содержит путь к каталогу, в котором расположены выбранные файлы, остальные строки содержат имена выбранных файлов. Выделение строки, содержащей путь к каталогу, проблем не вызывает, а чтобы получить имена выбранных файлов, необходимо воспользоваться методами GetStartPosition и GetNextPathName.
[pagebreak]
Метод GetStartPosition возвращает значение типа POSITION. Оно предназначено для передачи методу GetNextPathName и получения очередного имени выбранного файла. Если пользователь не выбрал ни одного файла, метод GetStartPosition возвращает значение NULL. Значение, полученное этим методом, следует записать во временную переменную типа POSITION и передать ссылку на нее методу GetNextPathName. Метод GetNextPathName вернет полный путь первого из выбранных в диалоговой панели файлов и изменит значение переменной pos, переданной методу по ссылке. Новое значение pos можно использовать для последующих вызовов метода GetNextPathName и получения путей всех остальных выбранных файлов. Когда метод GetNextPathName вернет имена всех выбранных файлов, в переменную pos записывается значение NULL.
В панелях Open и Save As имеется переключатель "ReadOnly". По умолчанию этот преключатель не отображается. Если есть необходимость воспользоваться этим переключателем, то нужно отказаться от использования флага OFN_HIDEREADONLY.
Метод GetReadOnlyPref позволяет определить положение переключателя "ReadOnly". Если переключатель включен, то метод GetReadOnlyPref возвращает ненулевое значение. В противном случае GetReadOnlyPref возвращает нуль.
Панель выбора шрифта (класс CFontDialog)
Стандартная диалоговая панель Font предназначена для выбора шрифта. Эта панель отображает список шрифтов, установленных в системе, и позволяет выбрать название шрифта, его начертание и другие параметры.
Для управления диалоговой панелью Font в библиотеку классов MFC включен класс CFontDialog. Методы этого класса можно использовать для отображения панели Font и определения характеристик шрифта, выбранного пользователем. Конструктор класса CFontDialog:
Все параметры конструктора являются необязательными. Настройка стандартной панели выбора шрифта, которая выполняется конструктором класса CFontDialog по умолчанию, удовлетворяет большинству пользователей.
Параметр lplfInitial является указателем на структуру LOGFONT, описывающую логический шрифт. Если этот параметр используется, то в диалоговой панели по умолчанию будет выбран шрифт, наиболее соответствующий шрифту, описанному в структуре LOGFONT.
Параметр dwFlags задает набор флагов, управляющий различными режимами работы панели. Например, флаг CF_EFFECTS позволяет пользователю создавать подчеркнутые и перечеркнутые буквы, определять цвет букв, а флаг CF_SCREENFONTS - разрешает выбирать только экранные шрифты.
Через параметр pdcPrinter можно передать конструктору контекст отображения принтера, шрифты которого будут представлены в диалоговой панели Font. Данный параметр используется только в том случае, если в параметре dwFlags указаны флаги CF_PRINTERFONTS или CF_BOTH.
Через параметр pParentWnd можно указать родительское окно для диалоговой панели Font.
Методы класса CFontDialog
Для отображения диалоговой панели Font предназначен виртуальный метод DoModal. Если пользователь выбрал шрифт и нажал кнопку OK, метод DoModal возвращает идентификатор IDOK, если пользователь отменил выбор шрифта, метод DoModal возвращает идентификатор IDCANCEL:
Остальные методы класса предназначены для определения характеристик выбранного пользователем шрифта.
Метод GetCurrentFont позволяет сразу определить все характеристики выбранного шрифта, записав их в структуру LOGFONT.
Остальные методы класса позволяют определить только отдельные характеристики выбранного шрифта:
GetFaceName - Возвращает имя выбранного шрифта
GetStyleName - Возвращает имя стиля выбранного шрифта
GetSize - Возвращает размер выбранного шрифта
GetColor - Возвращает цвет выбранного шрифта
GetWeight - Возвращает плотность выбранного шрифта
IsStrikeOut - Определяет, является ли шрифт выделенным перечеркнутой линией
IsUnderline - Определяет, является ли шрифт выделенным подчеркиванием
IsBold - Определяет, является ли шрифт жирным
IsItalic - Определяет, является ли шрифт наклонным
Панель для вывода документов на печать (класс CPrintDialog)
Класс CPrintDialog можно использовать для создания двух видов диалоговых панелей, предназначенных для печати документов и выбора форматов документов. Кроме класса CPrintDialog можно также использовать класс CPageSetupDialog. Он позволяет создать диалоговую панель для выбора формата документа, имеющую несколько иной вид.
В приложениях, подготовленных с использованием средств MFC AppWizard и построенные по модели документ-облик, по умолчанию встроена возможность вывода редактируемого документа на печать.
В меню File такого приложения находятся три строки (Print, Print Preview и Print Setup), которые управляют процессом печати документов, подготовленных в приложении. Чтобы распечатать документ, достаточно выбрать из меню File строку Print. На экране появится диалоговая панель Print. В ней можно выбрать печатающее устройство для печати документов (группа Name), указать, будет печататься весь документ либо его часть (группа Print range), а также сколько копий документа будет напечатано (группа Copies). Также можно настроить различные характеристики печатающего устройства, если нажать кнопку Properties в группе Printer.
Если требуется определить только печатающее устройство и формат документа, из меню File следует выбрать строку Printer Setup. В группе Printer можно указать печатающее устройство и настроить его соответствующим образом. Группа Paper задает формат бумаги и режим подачи бумаги в печатающее устройство. Группа Orientation включает только один переключатель, определяющий ориентацию бумаги. Он принимает положение Portrait для вертикальной ориентации изображения на бумаге (режим "портрет") или Landscape для горизонтальной ориентации изоборажения на бумаге (режим "ландшафт").
Строка Print Preview меню File выбирается для предварительного просмотра документа перед печатью. При этом главное окно приложения изменит свой внешний вид и можно будет просмотреть, как будет выглядеть документ после печати.
Если не требуется выполнять специфическую обработку документа перед печатью, то вряд ли понадобится самостоятельное добавление программного кода, отвечающего за процесс печати. Просто следует отметить, что процедура создания панелей, связанных с печатью документа, практически ничем не отличается от создания выше описанных стандартных диалоговых панелей.
Панель для выполнения поиска и замены (класс CFindReplaceDialog)
Класс CFindReplaceDialog предназначен для управления диалоговыми окнами Find и Replace. Диалоговая панель Find используется для поиска известных строк в документе приложения, а панель Replace позволяет замену одной строки на другую.
Важным отличием диалоговых панелей Find и Replace от других стандартных диалоговых панелей является то, что они представляют собой немодальные диалоговые панели. Поэтому процесс создания этих панелей значительно отличается от процесса создания стандартных панелей для выбора цвета, шрифта и имен файла.
Добавление сайта в каталоги уже давно и прочно вошло в список наиболее важных инструментов раскрутки и продвижения сайта в сети интернет. Сегодня мы расскажем о том, как с наилучшим результатом добавить свой сайт в каталоги. Есть два пути, при котором регистрация в каталогах влияет на посещаемость Интернет-ресурса:
Во-первых, каталоги предназначены для людей – в них человек может найти сайты по интересующей тематике. Среди таких посетителей каталогов есть и Ваши потенциальные клиенты. Таким образом, это Ваша реклама в каталоге. Примерами таких, приводящих посетителей, каталогов, является Яндекс.Каталог, рейтинг Рамблер.Top100, MAIL.ru и много других. Эти каталоги посещают миллионы пользователей ежедневно.
Во-вторых, любая поисковая система при ранжировании сайтов в выдаче по поисковому запросу учитывает количество и качество ссылок на ресурс, это так называемые индексы цитирования. У каждой поисковой системы он свой. У Яндекса - тИЦ (тематический индекс цитирования, применяется для ранжирования сайтов в Яндекс.Каталоге; можно увидеть на "денежке") и вИЦ (внутренний индекс цитирования, применяется для ранжирования сайтов в поисковой выдаче; не разглашается), у Google - PR (PageRank), у Апорта - ИЦ.
PageRank (PR) – рассчитывается для каждой веб-страницы отдельно, и определяется PageRank’ом (цитируемостью) ссылающихся на нее страниц. Своего рода замкнутый круг. Главная задача заключается в том, чтобы найти критерий, выражающий важность страницы. В случае с PageRank таким критерием была выбрана теоретическая посещаемость страницы.
тИЦ – тематический индекс цитирования – рассчитывается для сайта в целом и показывает авторитетность ресурса относительно других, тематически близких ресурсов (а не всех сайтов Интернета в целом). ТИЦ используется для ранжирования сайтов в каталоге Яндекса.
вИЦ – взвешенный индекс цитирования – аналог PageRank, применяемый поисковой системой Яндекс. Значения ВИЦ нигде не публикуются и известны только Яндексу. Поскольку узнать ВИЦ нельзя, следует просто помнить, что у Яндекса есть собственный алгоритм оценки «важности» страниц.
Добавляя свой сайт в каталог, Вы создаете дополнительную ссылку на него и повышаете таким образом свой индекс цитирования.
Стоит помнить, что просто повышая ИЦ, тИЦ, PR Вы мало чего добьетесь . Думаю, многие наблюдали ситуацию, когда на первой странице выдачи Яндекса вперед выходят сайты, имеющие меньший тИЦ, да и PR, чем у тех, кто занимает более низкие позиции. Для того чтобы использовать регистрацию в каталогах максимально эффективно, необходимо принять во вниманию ссылочное ранжирование. Дело в том, что этот фактор зачастую перевешивает многие другие, влияющие на место в поисковой выдаче.
Каким же образом действует ссылочное ранжирование? Формат гипертекста позволяет «на гиперссылке» ставить произвольный текст. Совпадение текста ссылок со словами поискового запроса (а особо точного вхождения) повышает Ваши позиции в выдаче.
Заметим также, что по низкочастотным запросам поисковики иногда выдают проиндексированные ими страницы каталогов со ссылкой на Ваш ресурс.
Таким образом, перед тем как регистрировать сайт в каталогах, составьте список запросов, по которым Вы хотели бы, чтобы Вас находили в поисковых системах. Для этого можно воспользоваться службами Подбора слов Яндекс.Директа и Статистикой поисковых запросов Рамблера.
Затем составьте несколько названий для Вашего сайта с использованием выбранных Вами ключевых слов. При этом учтите, что оптимальным будет использование словосочетаний, а не только отдельных слов, найденных Вами в статистике. Эти названия будут размещены на ссылке из каталога на Ваш сайт! Использование при регистрации в каталогах несколько названий позволит Вам использовать разные ключевые слова и избежать «превышения лимита» ссылок с одинаковым текстом, которые не учитываются поисковиками.
Названия должны быть осмысленными. Это обусловлено двумя причинами: во-первых, в последнее время поисковые системы очень плохо учитывают ссылки с перечислением ключевых слов через запятые. Во-вторых, большинство каталогов размещают ссылки после предварительной модерации. Те каталоги, которые следят за своим содержанием, с большой вероятностью откажут в размещении такой ссылки либо скорректируют ее на свое усмотрение, а как правило, ссылки именно с этих, серьезно модерируемых каталогов, имеют наибольший вес.
Адрес сайта указывать не обязательно, однако его присутствие в названии повышает Вашу узнаваемость среди многих других конкурентов. Еще раз повторю: не стоит перечислять ключевые слова через запятую, большое количество альтернативных названий позволит Вам использовать все выбранные Вами ключевые слова и даст значительно больше эффекта.
Выбирая рубрики, выбирайте наиболее подходящие. Зачем? Страница из подходящего раздела каталога получается самой подходящей с точки зрения «тематического» цитирования – это раз. Если раздел не подходит, модератор каталога (который тоже человек), может, не вдаваясь в подробности, просто отклонить сайт. Это два.
Для увеличения скорости выбора рубрик используйте Поиск. Обратите внимание на следующее: расставляйте слова в списке, начиная с наиболее подходящих, а затем по убыванию соответствия. В некоторых случаях, когда сложно предугадать, в каком склонении стоит слово в названии рубрики, используйте слова без окончаний. Иногда одно и то же слово может писаться по-разному. Учитывайте и это.
На заметку:
Обязательное условие успешной регистрации в каталогах и поисковиках - правильное описание ресурса и подбор ключевых слов. Иначе эффективность регистрации будет чрезвычайно мала.
Подача заявки на регистрацию еще вовсе не означает, что ресурс будет обязательно зарегистрирован. На это существует масса причин: неподходящая специализация каталога, некорректно составленное описание сайта, выбор неправильной категории, "заморочки" модераторов и проч. В среднем при хорошей предрегистрационной подготовке сайта, ресурс в течение месяца проходит регистрацию в 70-80% каталогов, куда была подана заявка.