Для начала разберемся, что такое
Для начала разберемся, что такое текстовые файлы и в чем их различие от двоичных файлов. Текстовые файлы являются подмножеством двоичных файлов, но в отличие от двоичных не могут содержать весь набор символов. Вся информация в файле разбивается на строки, ограниченные символам возврат каретки (CR) и перевод строки (LF). Допустимые символы это символы с кодами от 32 до 255, символы с кодами ниже 32 являются управляющими и допустимы только следующие коды:
Такая ситуация сложилась в стародавние время, когда устройством вывода были телетайпы, затем пишущие машинки и потом появились дисплеи. А каналы связи не позволяли передавать двоичные данные, да и сам они были сначала 5 битные, затем 7 битные и только потом таблицу символов расширили до 8 бит, для поддержки национальных языков и для полной совместимости с компьютерами, где основной единицей был байт. Остальные коды использовались или для управления каналом передачи или для управления специальными устройствами.
Паскаль поддерживает работу с такими файлами, через файловую переменную типа TextFile, где основной единицей является строка, состоящая из основных базовых типов (в текстовом виде, разделенных пробелом), наиболее часто это просто строка, как набор символов. В качестве примера напишем программу преобразования из DOS кодировки (OEM) в Windows (ANSI).
Техническое задание:
Текст программы
Program Oem2Ansi;
{$APPTYPE CONSOLE}
uses
Windows,
SysUtils;
var
InFile: TextFile;
OutFile: TextFile;
InFilename: string;
OutFilename: string;
S: string;
begin
if ParamCount = 0
then
begin
WriteLn('Syntax is: Oem2Ansi Infile [outfile]');
Halt(1); // Ошибка синтаксиса
end;
InFilename := ParamStr(1);
if ParamCount = 2
then
OutFileName := ParamStr(1)
else
OutFileName := ChangeFileExt(InFilename, '.ans');
AssignFile(InFile, InFilename); // связываем входной файл
AssignFile(OutFile, OutFilename); // и выходной выходной файл
try
try
Reset(InFile); // открываем входной файл
Rewrite(OutFile); // создаем выходной файл
while not EOF(InFile) do // крутим пока не конец файла
begin
Readln(Infile, S); // читаем строку
if Length(S) > 0 // на вход функции можно
then // подавать только не пустые строки
begin
OemToChar(Pchar(S), Pchar(S));
WriteLn(Outfile, S); // записываем строку
end
else
begin
WriteLn(Outfile); // записываем пустую строку
end;
end;
except
Halt(2); // любая ошибка
// не удалось преобразовать файлы
end;
finally
CloseFile(InFile);
CloseFile(OutFile);
end;
end.
Разберем работу программы по кусочкам. Вначале объявляются две файловые переменные текстового типа и две переменные для имен файлов, а также одна переменная для хранения и обработки строки. Затем анализируются входные параметры, если параметры не указываются, то выводится сообщение об ошибки и программа заканчивается с кодом выхода 1. Обратите внимание на форму процедуру WriteLn, если в параметрах не указывается файловая переменная, то вывод производится на консоль, что удобно для выдачи различных сообщений, данная форма возможна только для консольного приложения и не применима в GUI приложении.
После этого первый параметр копируется в переменную InFilename, если параметров два, то второй параметр копируется в переменную OutFilename, иначе используется имя входного файла и изменяется расширение, на расширение по умолчанию .ANS
После этого имена файлов связываются с файловыми переменными. Теперь мы готовы к преобразованию файла, которое будет делаться в двух защищенных блоках, первый блок для защиты ресурсов, а второй блок для защиты от возможных ошибок при работе с файлами, для любых ошибок возвращается код ошибки 2.
Первое действие состоит в открытии файлов, входной файл открывается с помощью процедуры Reset - это открытие текстового файла в режиме чтения, а второй с помощью Rewrite – открытие в режиме записи, если файл существует, то он переписывается. Есть еще одна форма открытия текстовых файлов, это функция Append(FileVar), открытие в режиме добавления строк, если файл существует, то курсор позиционируется в конец файла и файл открывается в режиме записи, если файла нет, то он создается. После нее управление передается в блок finally. В случае ошибки управление сначала передается в блок except, а затем в блок finally.
После этого создается цикл чтения строк, пока не будет достигнут конец файла, или физический или будет встречен символ EOF. Функция EOF(FileVar).
Внутри цикла читается строка во временную переменную Readln(Infile, S) и тут принята одна предосторожность, в функцию Oem2Char НЕЛЬЗЯ передавать пустые строки, поэтому производится анализ длины строки, если строка не нулевая, то производится конвертирование и запись ее в выходной файл, процедурой WriteLn(Outfile, S), иначе в файл пишется пустая строка.
По окончанию цикла или в случае ошибки управление поступает в защищенный блок finally, где оба файла закрываются и управление передается операционной системе.
Домашнее задание - переписать в Ansi2Oem для выполнения обратной функции, с тем же техническим заданием, расширение по умолчанию OEM
Для особо желающих предлагается сделать GUI версию, с диалогами выбора файлов, с прогресс-бар, с предварительным просмотром первых 10-20 строк входного файла (переключение кнопкой OEM/ANSI), с целью определения направления перекодирования, с остальными наворотами, которые сумеет придумать душа, например пакетная обработка всех файлов из папки.
Для разработки архива использован PHP 4.3.5, разработка скрипта