Программа-пример FileRev
Эта программа, «17 FileRev.exe» (см. листинг на рис. 17-2), демонстрирует, как с помо щью механизма проецирования записать в обратном порядке содержимое текстово го ANSI- или Unicode-файла. Файлы исходного кода и ресурсов чтой программы на ходятся в каталоге 17-FileRev на компакт-диске, прилагаемом к книге. После запуска FileRev на экране появляется диалоговое окно, показанное ниже.
Выбрав имя файла и щелкнув кнопку Reverse File Contents, Вы активизируете фун кцию, которая меняет порядок символов в файле на обратный, Программа коррект но работает только с текстовыми файлами. В какой кодировке создан текстовый файл (ANSI или Unicode), FileRev определяет вызовом IsTextUnicode (см. главу 2).
WINDOWS 98
В Windows 98 функция IsTextUnitode определена, но не реализована, она про сто возвращает FALSE, а последующий вызов GetLastError дает ERROR_CALL_ NOT_IMPLEMENTED. Это значит, что программа FileRev, выполняемая в Win dows 98, всегда считает, что файл содержит текст в ANSI-кодировке.
После щелчка кнопки Reverse File Contents программа создает копию файла с именем FileRev.dat, Делается это для того, чтобы не испортить исходный файл, изме нив порядок следования байтов на обратный. Далее программа вызывает функцию FileReverse — она меняет порядок байтов на обратный и после этого вызывает Create File, открывая FileRev.dat для чтения и записи
Как я уже говорил, простейший способ «перевернуть* содержимое файла — выз вать функцию _strrev из библиотеки С. Но для этого последний символ в строке дол жен быть нулевой. И поскольку текстовые файлы не заканчиваются нулевым симво лом, программа FileRev подписывает его в конец файла. Для этого сначала вызывает ся функция GetFileSize:
dwFileSize = GetFileSize(hFile, NULL);
Теперь, вооружившись знанием длины файла, можно создать объект "проекция файла", вызвав CreateFileMapping. При этом размер объекта равен dwFileSize плюс размер «широкого» символа, чтобы учесть дополнительный нулевой символ в конце файла. Создав объект "проекция файла", программа проецирует на свое адресное пространство представление этого объекта. Переменная pvFile содержит значение, возвращенное функцией MapViewOfFile, и указывает на первый байт текстового файла.
Следующий шаг — запись нулевого символа в конец файла и реверсия строки:
PSTR pchANSI = (PSFR) pvFile;
pchANSI[dwFileSize / sizeof(CHAR)] = 0;
// "переворачиваем" содержимое файла
_strrev(pchANSI);
В текстовом файле каждая строка завершается символами возврата каретки ("\r") и перевода строки ('\n') К сожалению, после вызова функции _strrev эти символы тоже меняются местами. Поэтому для загрузки преобразованного файла в текстовый ре дактор придется заменить все пары «\n\r» на исходные «\r\n». B программе этим за нимается следующий цикл.
while (pchANSI != NULL)
{
// вхождение найдено
*pchANSI++ = '\r ; // заменяем '\n' на '\r'
*pchANSI++ = '\n', // заменяем '\r на \n'
pchANSI = strchr(pchANSI, \n');
// ищем следующее вхождение
}
Закончив обработку файла, программа прекращает отображение на адресное про странство представления объекта «проекция файла» и закрывает описатель всех объ ектов ядра Кроме того, программа должна удалить нулевой символ, добавленный в конец файла (функция strrev не меняет позицию этого символа) Если бы програм ма не убрала нулевой символ, то полученный файл оказался бы на 1 символ длиннее, и тогда повторный запуск программы FileRev не позволил бы вернуть этот файл в исходное состояние Чтобы удалить концевой нулевой символ, надо спуститься на уровень ниже и воспользоваться функциями, предназначенными для работы непос редственно с файлами на диске.
Прежде всего установите указатель файла в требуемую позицию (в данном слу чае — в конец файла) и вызовите функцию SetEndOfFile:
SetFilePointer(hFile, dwFileSize, NULL, FILE_BEGIN);
SetEndOfFile(hFile);
NOTE:
Функцию SetEndOfFile нужно вызывать после отмены проецирования представ ления и закрытия объекта «проекция файла», иначе она вернет FALSE, а функ ция GetLastError — ERROR_USER_MAPPED_FILE. Данная ошибка означает, что операция перемещения указателя в конец файла невозможна, пока этот файл связан с объектом "проекция файла".
Последнее, что делает FileRev, — запускает экземпляр Notepad, чтобы Вы могли увидеть преобразованный файл. Вот как выглядит результат работы программы FileRev применительно к собственному файлу FileRev.cpp.
FileRev