"???" вместо русских букв (база данных FB, WIN1251)

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

62mkv
1.0.3 автоматически не перекодирует данные при запросе, в отличие от более новых версий. В этом у Вас и проблема. Так что советую сменить движок. ;)
Аватара пользователя
bloodlines
постоялец
Сообщения: 100
Зарегистрирован: 05.11.2008 10:26:19

Сообщение bloodlines »

У меня как раз возникла такая же проблема при переносе старой программы с Delphi 5 на Lazarus. Проблему я решил так:
Написал для Firebird собственную UDF позволяющую выполнять перекодировку текстовых данных прямо в запросе. Подключил UDF к базе и теперь когда выполняю запрос на выборку данных то пишу что то вроде

Код: Выделить всё

select
 ID_PARTNER,
 WINTOUTF( NAME ) as Name
FROM PARTNER

WINTOUTF как раз выполняет преобразование из WIN1251 в UTF8. В самой базе ничего не меняется.
А для UPDATE и INSERT операций использую UTFTOWIN ( опять же из своей UDF ). И проблем с базой нет вообще! UDF не влияет на работу других программ подключающихся к данной базе.
Если интересно - то могу поделиться исходником UDF ( изначально писалась на C, но теперь переписана на FPC ).
Аватара пользователя
dunin
энтузиаст
Сообщения: 634
Зарегистрирован: 02.05.2007 13:18:11
Откуда: Тољя††и
Контактная информация:

Сообщение dunin »

bloodlines писал(а):У меня как раз возникла такая же проблема при переносе старой программы с Delphi 5 на Lazarus. Проблему я решил так:
Написал для Firebird собственную UDF позволяющую выполнять перекодировку текстовых данных прямо в запросе.
...

Продолжительные аплодисменты! :roll:
Все гениальное просто. Хорошо, что не прочитал это сообщение пару месяцев назад - так и сидел бы на win1251... :D
Аватара пользователя
bloodlines
постоялец
Сообщения: 100
Зарегистрирован: 05.11.2008 10:26:19

Сообщение bloodlines »

Все гениальное просто. Хорошо, что не прочитал это сообщение пару месяцев назад - так и сидел бы на win1251...

Извините, но я не говорю, что WIN1251 это гуд, я всеми конечностями за Unicode и UTF8. Просто суть в моего вопроса (и как я понял вопроса автора темы) в том, что необходимо именно найти способ конвертации данных в UTF8 не меняя самой базы. В моём случае БД использовали кроме моей и сторонние проги, для которых WIN1251 - родная, потому UDF и писал. Никого сидеть на WIN1251 я не призываю.
Аватара пользователя
dunin
энтузиаст
Сообщения: 634
Зарегистрирован: 02.05.2007 13:18:11
Откуда: Тољя††и
Контактная информация:

Сообщение dunin »

bloodlines писал(а):Извините, но я не говорю, что WIN1251 это гуд, я всеми конечностями за Unicode и UTF8. Просто суть в моего вопроса (и как я понял вопроса автора темы) в том, что необходимо именно найти способ конвертации данных в UTF8 не меняя самой базы. В моём случае БД использовали кроме моей и сторонние проги, для которых WIN1251 - родная, потому UDF и писал. Никого сидеть на WIN1251 я не призываю.

Приношу извинения за пост, основанный на всплеске эмоций - они, как правило, двояко воспринимаются...

Никакого сарказма. Искренне восхищен простотой и очевидностью решения. Когда, в свое время, столкнулся с тем же - разрулить ситуацию при помощи UDF даже в голову ни пришло - ни смог придумать ничего лучше, как "рубануть кардинально" - изменить кодировку БД. В данный момент ушел от win1251 окончательно и возвращаться не собираюсь.
Аватара пользователя
bloodlines
постоялец
Сообщения: 100
Зарегистрирован: 05.11.2008 10:26:19

Сообщение bloodlines »

В данный момент ушел от win1251 окончательно и возвращаться не собираюсь.

Вот это правильно! Долой ущербные кодировки! На мой взгляд, если есть возможность то всегда следует использовать UNICODE.
Аватара пользователя
Brainenjii
энтузиаст
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Сообщение Brainenjii »

А кто-нибудь подскажет код для получения инициалов от имени и отчества для UTF-8 без всяких там Utf8Decode и подобного? Имя (ну и отчество) может как на буржуинском, так и на русском ^_^
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

ну можно так:

Код: Выделить всё

uses ...,LCLProc,...;
....
  I:=UTF8Copy(str,1,1);
....
Аватара пользователя
Brainenjii
энтузиаст
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Сообщение Brainenjii »

Спасибо ^_^ Правда, посмотрев как оно сделано, стало страшновато ^_^ Кстати, к вопросу о базах в cp1251 когда-то делали так - viewtopic.php?p=13945#p13945
fwp
новенький
Сообщения: 29
Зарегистрирован: 25.03.2008 11:00:06

Сообщение fwp »

62mkv писал(а):теперь исключение происходит (см. вложение)

Попробуй поменять localhost на другой. IP например. Только не 127.0.0.1 :D
62mkv
новенький
Сообщения: 10
Зарегистрирован: 27.03.2010 13:41:16
Откуда: Барнаул

Сообщение 62mkv »

мда. примерно понятно. конвертация БД это конечно очень хорошо.. однако с этой БД работает приложение которое мы не в силах пока пересобрать. а изменения вносить придется явно, потому что FB 1.5 (насколько я помню, но сейчас уже не уверен) несколько "капризнее" к запросам... в общем совместимость с приложением, которое написано для 1.0.3, никем не гарантируется, а ловить грабли в приложении которое ежедневно используют по 20 человек постоянно, и которое не можешь пересобрать - как то не хочется :)) тем более ради экспериментального проекта.

так что я уж пока как нибудь так. если будут другие варианты - прошу делиться !!

PS: UDF заценил, но "в КАЖДОМ ЗАПРОСЕ" ;)) че то лениво. проще один раз добиться и выяснить где и как этого (того же самого) можно добиться исправив FCL (зря что ли они OpenSource) и [пока] работать так..
Аватара пользователя
and
постоялец
Сообщения: 124
Зарегистрирован: 16.09.2009 17:11:01
Откуда: г. Гомель, Беларусь

Сообщение and »

62mkv писал(а):PS: UDF заценил, но "в КАЖДОМ ЗАПРОСЕ" ;)) че то лениво. проще один раз
...навесить на таблицу VIEW, в котором вызывать эти UDF абсолютно прозрачно для приложения.
andre_tur
незнакомец
Сообщения: 1
Зарегистрирован: 16.11.2011 15:04:49

Сообщение andre_tur »

Может уже устарело...
Но:
FB 2.1 Lazarus 0.9.30.2 - win32
в инспекторе объектов на IBConnection ставим CharSet utf-8 в коде :

Код: Выделить всё

procedure TForm1.FormShow(Sender: TObject);
begin
 IBConnection1.Charset:='win1251';
  SQLQuery1.Open;
end;

В рантайме - норма, в дизайне - ???.
Сам обыскался в И-нете. "Всё руками, всё руками..." :D
svk12
постоялец
Сообщения: 411
Зарегистрирован: 09.06.2008 18:42:47

Сообщение svk12 »

Не трогая БД, проще всего перекодировать текстовые поля непосредственно перед отображением.
Для этого надо:
1. Подключить модуль "lconvencoding".
2. Написать для полей отображаемого Датасета обработчик события onGetText.
Примерно такой:

Код: Выделить всё

procedure TForm1.AllText(Sender: TField; var AText: string;  DisplayText: Boolean);                                          
begin
    if Sender.DataType=ftString then AText:=CP1251ToUTF8(Sender.AsString)
  else
  AText:=Sender.AsString;                                             
end;


Привязывать этот обработчик к полям Датасета надо в обработчике события Датасета onAfterOpen:

Код: Выделить всё

procedure TForm1.DataSet1AfterOpen(DataSet: TDataSet);
 var i:integer;
begin
   With DataSet do
  begin         
    for i := 0 to Pred(FieldCount) do
    begin
        Fields[i].OnGetText:=AllText;
    end;                                     
  end;
end;
v-t-l
энтузиаст
Сообщения: 744
Зарегистрирован: 13.05.2007 16:27:22
Откуда: Belarus

Сообщение v-t-l »

Код: Выделить всё

procedure TForm1.FldGetText(Sender: TField; var AText: string;  DisplayText: Boolean);                                         
begin
  AText:=CP1251ToUTF8(Sender.AsString);
end;

procedure TForm1.FldSetText(Sender: TField; const AText: string);                                         
begin
  Sender.AsString:=UTF8ToCP1251(AText);
end;

procedure TForm1.DataSet1AfterOpen(DataSet: TDataSet);
var i:integer;
begin
  With DataSet do
  begin         
    for i := 0 to Pred(FieldCount) do
      if Fields[i].DataType in [ftString, ftMemo] then
      begin
        Fields[i].OnGetText:=@FldGetText;
        Fields[i].OnSetText:=@FldSetText;
      end;                                     
  end;
end;
Ответить