Пятница, 17.05.2024, 10:10
Главная Регистрация RSS
Приветствую Вас, Гость
Главная » Delphi и механизмы Windows » Преобразование форматов текстовых документов. Формат MS DOS
10:16

Преобразование форматов текстовых документов. Формат MS DOS

Для текстовых документов существуют две совершенно различные кодировки — Windows и MS DOS. Обычно приложения Windows используют, естественно, для текстов кодировку Windows. Но если какие-то файлы должны читаться, например, в Norton Commander или в других приложениях DOS, надо применять кодировку MS DOS. Применение этой кодировки требуется также при разработке консольных приложений Win32.

Для взаимного перевода текста в текст DOS и обратно в API Windows предусмотрены две процедуры: CharToOem — перевод в формат DOS, и OemToChar - перевод из формата DOS в «только текст». Они объявлены в модуле Windows. Для VCL Win32 объявления имеют вид:


function CharToOem(lpszSrc: PAnsiChar; lpszDst: PAnsiChar): BOOL; 
function OemToChar(lpszSrc: PAnsiChar; lpszDst: PAnsiChar): BOOL; 
function CharToOem(lpszSrc: string; lpszDst: StringBuilder): BOOL; 
function OemToChar(lpszSrc: string; lpszDst: StringBuilder): BOOL; 

Обе процедуры принимают два параметра типа PAnsiChar, первый из которых — указатель на строку переводимого текста, а второй — указатель на строку результата перевода.

Приведу сначала пример консольного приложения VCL Win32:


program Projectl; 
{$APPTYPE CONSOLE} 
uses 
Windows; 
var S: array[0..255] of char; 
SI: string; 
begin 
CharToOem('Привет! Введите свое имя:1, S); 
Writeln (S); 
Readln(Sl); 
OemToChar(PChar(SI), PChar (SI)); 
SI := 'Привет, ' + SI; 
CharToOem(PChar(SI), S); 
Writeln(S); 
Readln; 
end. 

Приложение выводит пользователю приглашение: «Привет! Введите свое имя:». Если пользователь в ответ вводит имя, например, «Иванов», то приложение затем печатает текст «Привет, Иванов» и ждет, пока пользователь нажмет клавишу Enter.

Если бы приглашение пользователю выводилось простым оператором:

Writeln('Привет! Введите свое имя:’);
то пользователь увидел бы на экране абракадабру, в которой смог бы узнать только восклицательный знак и двоеточие. Это связано с тем, что консольное приложение работает в окне DOS, в котором символы кириллицы должны задаваться в кодировке MS DOS. Поэтому первый оператор приведенного выше кода переводит функцией CharToOem текст приглашения в эту кодировку. Далее обычной функцией Writeln этот текст выводится на экран. Функция Readln читает введенный пользователем ответ в строку S1. Если бы дальше эту строку надо было бы в какой-то момент выводить на экран, ее перекодировку можно было бы не делать. Но в данном приложении введенный текст надо объединить с текстом «Привет, ». Поэтому строка функцией OemToChar переводится в кодировку Windows, затем объединяется с требуемым текстом и затем переводится в кодировку MS DOS. После этого она может выводиться на экран.

В консольных приложениях VCL .NET никаких сложностей с отображением и чтением русских текстов не возникает. Так что в них нет необходимости использовать функции CharToOem и OemToChar. Приведенное выше приложение в VCL .NET существенно упрощается:


program Projectl; 
{$APPTYPE CONSOLE} 
var S: string; 
begin 
Writeln('Привет! Введите свое имя:1); 
Readln(S); 
Writeln('Привет, ' + S) ; 
Readln; 
end.

Теперь вернемся к основной теме данного раздела — кодировке документов. Если вы хотите включить в свое приложение VCL Win32 кнопку, осуществляющую перевод загруженного в компонент RichEditl текста из файла в формате DOS в текстовый формат (т.е. перевести абракадабру, которую видит пользователь, в нормальный текст), обработчик щелчка на этой кнопке может быть таким:


procedure TForml.ButtonOemToCharClick(Sender: TObject); 
var s: string; 
begin 
SetLength(s, Length(RichEditl.Text)); 
OemToChar(PChar(RichEditl.Text), PChar (s)); 
RichEditl.Text := s; 
end;

В обработчике вводится локальная переменная s типа string. Первый оператор обработчика устанавливает функцией SetLength размер этой строки равным размеру текста в окне RichEditl. Следующий оператор функцией OemToChar переводит текст, записанный в окне RichEditl, в текстовый формат и заносит результат в подготовленную строку s. А последний оператор возвращает эту строку в компонент RichEditl.

Конечно, в реальном приложении, возможно, лучше аналогичный код вставить в процедуру открытия файла. Тогда после выбора пользователем файла можно определить, является ли он текстовым, т.е. с расширением ".txt" (способ определения расширения файла вы могли видеть в одном из рассмотренных примеров открывания файла). Если файл оказался с расширением ".txt", можно спросить у пользователя, требуется ли проводить преобразование формата из «текста DOS», и если требуется, то произвести указанные выше преобразования.

Выше было рассмотрено преобразование формата текста окна RichEdit в приложениях VCL Win32. В приложениях VCL .NET подобное преобразование производится совершенно иначе. Дело в том, что функции CharToOem и OemToChar в VCL .NET объявлены иначе:


function CharToOem(lpszSrc: string; lpszDst: StringBuilder): BOOL; 
function OemToChar(lpszSrc: string; lpszDst: StringBuilder): BOOL;

Параметр lpszSrc — это преобразуемая строка, а параметр lpszDst — это построитель строк класса StringBuilder, который воспринимает результат преобразования. Не будем останавливаться на причинах, по которым в обращениях к функциям API Windows в .NET в качестве выходных параметров задается StringBuilder. Для наших целей достаточно знать, что объект StringBuilder надо сначала создать с помощью его конструктора, в который передается размер строки, а после преобразования текста результирующую строку можно прочитать методом ToString.

Прежде, чем рассматривать преобразование текста DOS, загруженного в окно RichEdit, надо отметить, что загрузка файла в формате DOS произойдет правильно, только если свойство PlainText окна RichEdit в этот момент установлено в false. Иначе текст загрузится, но его дальнейшее преобразование будет невозможным. Впрочем, по умолчанию PlainText = false.

А теперь рассмотрим код, обеспечивающий перевод текста в формате DOS, загруженного в окно RichEdit1, в текстовый формат:


procedure TForml.ButtonOemToCharClick(Sender: TObject); 
var SB: StringBuilder; 
S: String; 
SCodel, SCode2: String; 
i: Integer; 
begin 
// создание объекта SB 
SB := StringBuilder.Create(Length(RichEditl.Text) * 2); 
// преобразование текста 
OemToChar(RichEditl.Text, SB); 
// получение преобразованного текста в виде строки 
S := SB.ToString; 
// следующие операторы заменяют в тексте символы 
// новой строки и возврата каретки 
// строка символов новой строки и возврата каретки 
SCodel :=.#13#10; 
// строка символов новой строки и возврата каретки в DOS 
OemToChar(SCodel, SB); 
SCode2 := SB.ToString; 
// замена символов 
i := Pos(SCode2, S); 
while i > 0 do 
begin 
S := Copy(S, 1, i-1) + SCodel + Copy(S, i + Length(SCodel), 1000); 
i := Pos(SCode2, S); 
end; 
RichEditl.Text := S; 
end;

В коде вводится переменная SB класса StringBuilder. Первый выполняемый оператор создает объект SB вызовом его конструктора Create. В конструктор передается размер строки, которую может хранить объект. Этот размер задается как удвоенное число символов текста, поскольку каждый символ занимает 2 байта. Вызов функции OemToChar переводит текст RichEditl.Text и заносит результат в SB. На этом можно было бы закончить перевод и отобразить результат в окне оператором

RichEditl.Text := SB.ToString;

Если вы это сделаете, то увидите, что текст перевелся и вместо абракадабры в окне появился русский текст. Но не перевелись символы новой строки и возврата каретки, которыми завершается каждая строка текста в окне RichEdit. Вместо них в окне отображаются непечатаемые символы, а разбиение исходного текста на строки пропало. Так что надо заменить эти непечатаемые символы обычными символами новой строки и возврата каретки. А чтобы не проводить эту замену непосредственно в тексте окна, результат перевода исходного текста заносится сначала в переменную S.

Для замены символов в коде предусмотрены строковые переменные SCodel и SCode2. В первую из них заносятся символы новой строки и возврата каретки — #13#10. Затем для этой строки вызывается функция OemToChar, и результат переносится в переменную SCode2. Таким образом, в SCode2 создается комбинация символов, в которую переводится функцией OemToChar последовательность символов #13#10. Теперь надо заменить в строке S все вхождения символов SCode2 символами SCodel. Это делается в цикле while. В заключение строка S переносится в текст окна RichEditl.

Рассмотрим теперь, как обеспечить возможность сохранения файла в формате текста DOS. Для этого в компонент SaveDialog, используемый при сохранении, можно ввести следующие фильтры:

в формате RTF *.rtf 
только текст *.txt 
текст DOS *.txt 

Тогда процедуру сохранения в файле в приложении VCL Win32 можно оформить следующим образом:


var s: string; 
F: TextFile; 
begin 
if SaveDialogl.Execute 
then begin 
if (SaveDialogl.Filterlndex = 3) 
then begin 
SetLength(s, Length(RichEditl.Text)); 
CharToOem(PChar(RichEditl.Text), PChar (s)); 
AssignFile(F, SaveDialogl.FileName); 
Rewrite(F); 
Write(F,s); 
CloseFile(F); 
end 
else RichEditl.Lines.SaveToFile(SaveDialogl.FileName) 
end; 
end; 

Если пользователь в диалоге выбрал фильтр «текст DOS» (третий из указанных фильтров), то длина строки локальной переменной s устанавливается равной длине текста в окне редактирования, в нее читается переведенный с помощью функции CharToOem текст, а затем методами работы с текстовыми файлами строка записывается в указанный пользователем файл.

Поскольку функция CharToOem объявлена в VCL .NET, как уже говорилось, иначе, код в приложении VCL .NET должен быть другим. Например, таким:


var s: string; 
SB: StringBuilder; 
begin 
if SaveDialogl.Execute 
then begin 
if (SaveDialogl.Filterlndex = 3) 
then begin 
SB := StringBuilder.Create(Length(RichEditl.Text) * 2); 
CharToOem(RichEditl.Text, SB); 
s := RichEditl.Text; 
RichEditl.Text := SB.ToString;; 
RichEditl.Lines.SaveToFile(SaveDialogl.FileName); 
RichEditl.Text := s; 
end 
else RichEditl.Lines.SaveToFile(SaveDialogl.FileName) 
end; 
end; 

Если пользователь в диалоге выбрал фильтр "текст DOS", то создается объект SB класса StringBuilder и результат преобразования текста в формат DOS заносится в этот объект. Далее в промежуточной переменной s сохраняется исходный текст окна RichEditl и в это окно заносится преобразованный текст. Он сохраняется методом SaveToFile, после чего текст в окне восстанавливается.

Категория: Delphi и механизмы Windows | Просмотров: 8729 | Добавил: PeKpyT | Рейтинг: 0.0/0
Всего комментариев: 2
1 тороплюсь  
0
млин как много букв, мне некогда читать плиз кто-нить киньте код для преобразования текстового файла из ms-dos в windows, спасибо скажу абязательно)

2 Sam  
0
блин(
всеравно все криво выводиться, одни кракозябы

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]