туда и обратно или работа с кодировками

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

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

туда и обратно или работа с кодировками

Сообщение nic1982 » 20.05.2011 12:05:57

Есть проблема с кодировками или же с пониманием работы с БД.

1-я задача
простейший текстовый редактор, проблем нет, есть функции типа "ИЗ-->В" (CP866ToUTF8) все просто и понятно.

2-я задача
простейший редактор DBF, тут уже сложней и мениие понятней
как используя TDBF, DataSource, DBGrid считывать из DBF-а в CP866 отобразить в DBGrid-e в UTF8 ?
и обратно из DBGrid-a измененные/добавлиные записи в DBF файл из UTF8 в CP866 ?

3-я задача
теперь уже работа с СУБД FireBird

a) не могу понять где перекодировать данные в DBGrid, DataSource, ... ?
как из СУБД FireBird они проходят в DBGrid и обратно ?

b) как из DBF файла с кодировкой cp866(cp1125) перенести данные в СУБД FireBird с кодировкой UTF8(CP1251) ?
на этот вопрос ответ может быть получен из 2-й задачи
желательно собственная разработка а не стороння утилита

c) как из СУБД FireBird кодовая страница CP1251 отображать в DBGrid-e в UTF8 ?
nic1982
новенький
 
Сообщения: 48
Зарегистрирован: 17.05.2011 16:34:05

Re: туда и обратно или работа с кодировками

Сообщение Timid » 21.05.2011 09:19:22

Чтобы получше разобраться, начните с изучения работы с кодировкой под Delphi.

(Если лень читать) Суть в том, что кодировка теперь является свойством строки, так же как и ее длина. В книжках по FreePascal об этом не пишут, кстати, а зря (или их авторы не разбираются в этом?).
Так вот, при присвоении строк происходит автоматическое перекодирование в соответствии с кодовыми таблицами, чтобы, к примеру, русское "А" всегда было им. В Вашей первой задаче:
Код: Выделить всё
var
  c:AnsiString(866); // не уверен с кодом кодировки CP866
  s:UTF8String;
begin
  c:="ВАСЯ";  // 4 байта
  s:=c;           // перекодирование "по смыслу", в s теперь 8 байт
  Label1.Caption:= s;       // выводит "ВАСЯ"
Timid
постоялец
 
Сообщения: 290
Зарегистрирован: 21.11.2007 21:33:15

Re: туда и обратно или работа с кодировками

Сообщение Odyssey » 21.05.2011 11:17:21

Timid
Работа с кодировками во FreePascal/Lazarus сейчас отличается от того, что сделано в Delphi после перехода на юникод. Строки во FreePascal НЕ хранят информацию о кодировке. Работа над этим ведётся в отдельной ветке (cpstrnew), и когда эти изменения попадут в основную ветку -- неизвестно.

nic1982
Ответы на некоторые вопросы, возможно, появятся после просмотра этой ветки англоязычного форума:
http://www.lazarus.freepascal.org/index ... pic=5963.0
и этой ветки русского:
http://www.freepascal.ru/forum/viewtopi ... =26&t=4481
Ничего более конкретного посоветовать, к сожалению, не могу - ни с DBF, ни с Firebird не работал.
Odyssey
энтузиаст
 
Сообщения: 580
Зарегистрирован: 29.11.2007 17:32:24

Re: туда и обратно или работа с кодировками

Сообщение Timid » 21.05.2011 23:11:17

Odissey, хм, это плохо.
Раньше переносить проекты из Delphi было проще, теперь, когда все уже переписано под XE, а в Лазаре еще "конь не валялся" со строками :(

Отсюда вывод - нужно лезть в DataSource - писать свою обертку над потоком данных. Для перекодировки "на лету"
Timid
постоялец
 
Сообщения: 290
Зарегистрирован: 21.11.2007 21:33:15

Re: туда и обратно или работа с кодировками

Сообщение v-t-l » 23.05.2011 09:49:05

Вот такой костыль можно применить:
Код: Выделить всё
uses lconvencoding;

{ TForm1 }

procedure TForm1.DbFieldGetText(Sender: TField; var aText: string;
  DisplayText: Boolean);
begin
  aText:=CP866ToUTF8(Sender.AsString);
end;

procedure TForm1.DbFieldSetText(Sender: TField; const aText: string);
begin
  Sender.AsString:=UTF8ToCP866(aText);
end;

procedure TForm1.DbAfterOpen(DataSet: TDataSet);
var i: Integer;
begin
  for i:=0 to DataSet.FieldCount-1 do
    if DataSet.Fields[i].DataType in [ftString, ftMemo, ftFixedChar] then
    begin
      DataSet.Fields[i].OnGetText:=@DbFieldGetText;
      DataSet.Fields[i].OnSetText:=@DbFieldSetText;
    end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
begin
  for i:=0 to ComponentCount-1 do
    if Components[i] is TDataSet then
    begin
      (Components[i] as TDataSet).AfterOpen:=@DbAfterOpen;
      if (Components[i] as TDataSet).Active then
        DbAfterOpen(Components[i] as TDataSet);
    end;
end;
v-t-l
энтузиаст
 
Сообщения: 735
Зарегистрирован: 13.05.2007 16:27:22
Откуда: Belarus

Re: туда и обратно или работа с кодировками

Сообщение Ism » 23.05.2011 14:25:37

Лучше перевести базы в utf8 и раз и навсегда и забыть о костылях.

На худой конец работать в одну сторону, импортировать новые данные из dbf в свою базу в utf8
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 49

Рейтинг@Mail.ru