Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Программирование для начинающих и не только


Информационный Канал Subscribe.Ru

©Gigabyte 2004

По материалам www.gigabyte.iatp.org.ua

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

Постановка задачи

Итак. У нас есть кириллический текст с наперед известной кодировкой:

  • CP1251 - Кодовая страница Windows
  • ISO8859-5 - ISO-страница
  • KOI8-U - Кодовая страница используемая практически во всех версиях в Unix
  • MAC-U - Страница используемая в MacOS
  • RUSCII - или старая добрая CodePage 866 известная всем жившим в период DOS.
Теперь же нам требуется предоставить пользователю возможность прочесть этот текст в нормальном виде. Для этого нам надобно перевести текст с этой кодовой страницы в ту, которая используется системой в данный момент, а так как большинство читателей используют в своей повседневной жизни Windows, то текст мы будем приводить в соответствие со стандартной кодовой страницей Windows - CP1251.

Решение

Решение данной задачи не столько сложно в плане логическом, сколько в технологическом. Так как тем программистам, которые специально не занимались этой проблемой бывает довольно трудно отыскать ту или иную кодовую страницу, а потом с первого раза привести ее в "рабочий" вид.

Теперь пристально вглядевшись в таблицы кодировок (рис.1 - рис.5) мы замечаем, что вся разница в кодовых страницах начинает проявляться только для второй половины таблицы (т.е. для символов с кодами 128-255, которые и изображены на рисунках). Теперь нам только понадобится вручную сопоставить коды из каждой таблицы в соответствии с кодами текущей кодовой страницы (CP1251). (см. Листинг 1).

Сам алгоритм может варьироваться от програмиста к програмисту. Но суть его должна быть одна и та же: выбрать символ, просмотреть таблицу перекодировки и если найдено совпадение - заменить символ. Примерный код алгоритма перебора подан ниже:


For j:=1 to Length(S) do
 if Byte(S[j])>=Low(A) then
  For i:=Low(A) to High(A) do
   begin
    if Byte(S[j])=i then
     begin
      S[j]:=A[i];
      break;
     end;
   end;
    Здесь:
  • S - строка текста, которую следует перекодировать
  • A - массив перекодировки символов из соответствующей кодировки в CP1251.

"Подводные камни"

Хотя приведенный алгоритм не смотря на простоту реализации и дает необходимый результат, но при прямом его использовании могут возникнуть некоторые несоответствия называемые "двойной перекодировкой". Так к примеру получается, если мы перетаскиваем текст (через буфер обмена) из какой-то программы работающей в кодировке KOI8 в текстовый редактор (к примеру Far - F4), Который в это время находится в режиме редактирования DOS - текста (рис.6 - рис.7). Тот же эффект можно видеть и при любых других комбинациях кодировок. Как раз для этого в таких продвинутых в кодовом плане программах как TheBat! предусмотрена "двойная перекодировка"(рис.8).

И конечно же не стоит упоминать о том что можно найти текст, разные части которого написаны в разных кодировках, или, что еще хуже, с использованием разных вариантов "двойной перекодировки". Все эти ухищрения отнюдь не облегчают проблему распознавания кодировок, и заставляют программистов искать более совершенные методы эвристического анализа текста.

Выводы

Конечно эта маленькая заметка не претендует на роль всеобъемлющего руководства для построения "мультикодовых" приложений. Она всего лишь маленький шаг направленный в сторону облегчения общения людей работающих в разных средах, использующих различные ОС и ПО. И конечно же основная работа для обеспечения поддержки программами различных кодировок, или даже поддержки автоматического распознавания кодировок, возлагается как всегда на Вас - разработчиков этих самых программ.


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TCodepageArray = array[$80..$FF] of Char;
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    Codetable: TRadioGroup;
    FileName: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

const
 ruscii:TCodepageArray =
 ('А','Б','В','Г','Д','Е','Ж','З','И','Й','К','Л','М','Н','О','П',
  'Р','С','Т','У','Ф','Х','Ц','Ч','Ш','Щ','Ъ','Ы','Ь','Э','Ю','Я',
  'а','б','в','г','д','е','ж','з','и','й','к','л','м','н','о','п',
  #176,#177,#178,#179,#180,#181,#182,#183,#184,#185,#186,#187,#188,#189,#190,#191,
  #192,#193,#194,#195,#196,#197,#198,#199,#200,#201,#202,#203,#204,#205,#206,#207,
  #208,#209,#210,#211,#212,#213,#214,#215,#216,#217,#218,#219,#220,#221,#222,#223,
  'р','с','т','у','ф','х','ц','ч','ш','щ','ъ','ы','ь','э','ю','я',
  'Ё','ё','Г','г','Є','є','I','i','Ї','ї',#250,#251,#252,#253,#254,#255);

 koi8u:TCodepageArray =
 (#128,#129,#130,#131,#132,#133,#134,#135,#136,#137,#138,#139,#140,#141,#142,#143,
  #144,#145,#146,#147,#148,#149,#150,#151,#152,#153,#154,#155,#156,#157,#158,#159,
  #160,#161,#162,'ё' ,'є' ,#165,'i' ,'ї' ,#168,#169,#170,#171,#172,#173,#174,#175,
  #176,#177,#178,'Ё' ,'Є' ,#181,'I' ,'Ї' ,#184,#185,#186,#187,#188,#189,#190,#191,
  'ю' ,'а' ,'б' ,'ц' ,'д' ,'е' ,'ф' ,'г' ,'х' ,'и' ,'й' ,'к' ,'л' ,'м' ,'н' ,'о' ,
  'п' ,'я' ,'р' ,'с' ,'т' ,'у' ,'ж' ,'в' ,'ь' ,'ы' ,'з' ,'ш' ,'э' ,'щ' ,'ч' ,'ъ' ,
  'Ю' ,'А' ,'Б' ,'Ц' ,'Д' ,'Е' ,'Ф' ,'Г' ,'Х' ,'И' ,'Й' ,'К' ,'Л' ,'М' ,'Н' ,'О' ,
  'П' ,'Я' ,'Р' ,'С' ,'Т' ,'У' ,'Ж' ,'В' ,'Ь' ,'Ы' ,'З' ,'Ш' ,'Э' ,'Щ' ,'Ч' ,'Ъ' );

 cp1251:TCodepageArray =
 (#128,#129,#130,#131,#132,#133,#134,#135,#136,#137,#138,#139,#140,#141,#142,#143,
  #144,#145,#146,#147,#148,#149,#150,#151,#152,#153,#154,#155,#156,#157,#158,#159,
  #160,#161,#162,#163,#164,#165,#166,#167,#168,#169,#170,#171,#172,#173,#174,#175,
  #176,#177,#178,#179,#180,#181,#182,#183,#184,#185,#186,#187,#188,#189,#190,#191,
  #192,#193,#194,#195,#196,#197,#198,#199,#200,#201,#202,#203,#204,#205,#206,#207,
  #208,#209,#210,#211,#212,#213,#214,#215,#216,#217,#218,#219,#220,#221,#222,#223,
  #224,#225,#226,#227,#228,#229,#230,#231,#232,#233,#234,#235,#236,#237,#238,#239,
  #240,#241,#242,#243,#244,#245,#246,#247,#248,#249,#250,#251,#252,#253,#254,#255);

 iso88595:TCodepageArray =
 (#128,#129,#130,#131,#132,#133,#134,#135,#136,#137,#138,#139,#140,#141,#142,#143,
  #144,#145,#146,#147,#148,#149,#150,#151,#152,#153,#154,#155,#156,#157,#158,#159,
  #160,'Ё' ,#162,#163,'Є' ,#165,'I' ,'Ї' ,#168,#169,#170,#171,#172,#173,#174,#175,
  'А' ,'Б' ,'В' ,'Г' ,'Д' ,'Е' ,'Ж' ,'З' ,'И' ,'Й' ,'К' ,'Л' ,'М' ,'Н' ,'О' ,'П' ,
  'Р' ,'С' ,'Т' ,'У' ,'Ф' ,'Х' ,'Ц' ,'Ч' ,'Ш' ,'Щ' ,'Ъ' ,'Ы' ,'Ь' ,'Э' ,'Ю' ,'Я' ,
  'а' ,'б' ,'в' ,'г' ,'д' ,'е' ,'ж' ,'з' ,'и' ,'й' ,'к' ,'л' ,'м' ,'н' ,'о' ,'п' ,
  'р' ,'с' ,'т' ,'у' ,'ф' ,'х' ,'ц' ,'ч' ,'ш' ,'щ' ,'ъ' ,'ы' ,'ь' ,'э' ,'ю' ,'я' ,
  #240,'ё' ,#242,#243,'є' ,#245,'i' ,'ї' ,#248,#249,#250,#251,#252,#253,#254,#255);
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var SL:TStringList;i:byte;j:integer;
    S:String;
    A:TCodepageArray;
begin
SL:=TStringList.Create;
try
SL.LoadFromFile(FileName.Text);
S:=SL.Text;
if CodeTable.ItemIndex=0 then A:=ruscii else
if CodeTable.ItemIndex=1 then A:=koi8u else
if CodeTable.ItemIndex=2 then A:=cp1251 else
if CodeTable.ItemIndex=3 then A:=iso88595;
For j:=1 to Length(S) do
 if Byte(S[j])>=Low(A) then
  For i:=Low(A) to High(A) do
   begin
    if Byte(S[j])=i then
     begin
      S[j]:=A[i];
      break;
     end;
   end;
finally
Memo1.Text:=S;
SL.Free;
end;
end;

end.
©Gigabyte 2004

http://subscribe.ru/
http://subscribe.ru/feedback/
Подписан адрес:
Код этой рассылки: comp.soft.prog.programmershelp
Отписаться

В избранное