TDbf и ОЕМ кодировка

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

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

SAK
постоялец
Сообщения: 158
Зарегистрирован: 17.02.2006 23:45:14
Откуда: Тим
Контактная информация:

Сообщение SAK »

Имеется-ли возможность работать в TDbf с таблицами в DOS кодировке, если да, то где это включается?
Аватара пользователя
STAKANOV
энтузиаст
Сообщения: 1069
Зарегистрирован: 14.05.2006 21:26:24
Откуда: Зеленоград

Сообщение STAKANOV »

По-моему это никак не контролируется. Я работал с tdbf в Linux и записывал в поля типа ftString данные, открыв файл в Windows, я обнаружил, что у меня все записано в кодировке KOI8-R :D
Guest

Сообщение Guest »

хе млять...
хоть кто-то еще с этим столкнулся...
я долго парился с этими кодировками...
потом зделал тупо, взял функцию которая преобразовывает win1251 -> koi8-r и наоборот... ну и для остальных кодировок тоже есть...
в понедельник если интересно смогу дать эти функции...
Аватара пользователя
STAKANOV
энтузиаст
Сообщения: 1069
Зарегистрирован: 14.05.2006 21:26:24
Откуда: Зеленоград

Сообщение STAKANOV »

в понедельник если интересно смогу дать эти функции...

у меня есть, я сейчас как раз программулинку пишу которая текстовые файлы перекодирует

хотя остальные кодировки это какие?
а то тут только win,koi8r,dos и какой-то iso

я взял от сюда - <a href='http://pascal.sources.ru/text/coder.zip' target='_blank'>http://pascal.sources.ru/text/coder.zip</a>
Janus
постоялец
Сообщения: 134
Зарегистрирован: 07.11.2005 16:06:49

Сообщение Janus »

Вот универсальная функция:

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

    function  convert_cyr_string(str : string; from, to_ : char) : string;
  var
    i       : integer;
    p       : integer;
    c       : char;
    fromstr : string;
    tostr   : string;
  begin
    case from of
      'w' : fromstr := 'абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ';
      'd' : fromstr :=  #160#161#162#163#164#165#241#166#167#168#169#170#171#172#173#174#175#224#225#226#227#228#229#230#231#232#233#234#235#236#237#238#239#128#129#130#131#132#133#240#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;
      'k' : fromstr := 'БВЧЗДЕJЦЪЙКЛМНОПРТУФХЖИГЮЫЭЯЩШЬАСбвчздеjцъйклмнопртуфхжигюыэящшьас';
    else
            fromstr := 'абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ';
    end;
    case to_ of
      'w' : tostr := 'абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ';
      'd' : tostr :=  #160#161#162#163#164#165#241#166#167#168#169#170#171#172#173#174#175#224#225#226#227#228#229#230#231#232#233#234#235#236#237#238#239#128#129#130#131#132#133#240#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;
      'k' : tostr := 'БВЧЗДЕJЦЪЙКЛМНОПРТУФХЖИГЮЫЭЯЩШЬАСбвчздеjцъйклмнопртуфхжигюыэящшьас';
    else
            tostr := 'абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ';
    end;

    for i := 1 to length(str) do
    begin
      c := str[i];
      p := pos(c, fromstr);
      if p <> 0 then
      begin
        c      := tostr[p];
        str[i] := c;
      end;
      str[i] := c;
    end;

    convert_cyr_string := str;
  end;

Конечно, можно еще немного оптимизировать, но работает.

from (из) и to_ (в) показывают направление кодировки:
w - ANSI
d - ASCII
k - KOI8R
Аватара пользователя
STAKANOV
энтузиаст
Сообщения: 1069
Зарегистрирован: 14.05.2006 21:26:24
Откуда: Зеленоград

Сообщение STAKANOV »

учитывая что tdbf работае с форматами(задается в TableLevel)
3 dBase III+
4 dBase IV
7 Visual dBase VII
25 FoxPro


то по-умолчанию всегда надо использовать cp1251 для хранения данных.
SAK
постоялец
Сообщения: 158
Зарегистрирован: 17.02.2006 23:45:14
Откуда: Тим
Контактная информация:

Сообщение SAK »

Вчера посмотрел исходники и обнаружил там функцию TDbf.Translate.
Которая, как я понимаю, задумывалась как раз для перекодировки, но почему-то не применяется при чтении/записи данных полей базы, но зато используется для перекодирования Memo полей, что в общем случае делать нельзя, т.к. там может быть не только текст, но и двоичные данные. Либо я не понял назначения этой функции, либо она очень криво построена.

Пока ограничился изменением 2-х функций:

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

function TDbf.GetFieldData(Field: TField; Buffer: Pointer; NativeFormat: Boolean): Boolean; {overload; override;}
begin
  // pretend nativeformat is true
  Result := inherited GetFieldData(Field, Buffer, True);
  if (Field.DataType = ftString)and(Buffer<>nil) then
    OemToCharBuff(Buffer, Buffer, Field.DataSize);
end;

procedure TDbf.SetFieldData(Field: TField; Buffer: Pointer; NativeFormat: Boolean); {overload; override;}
var buf: array[0..1024]of char;
begin
  if (Field.DataType = ftString)and(Buffer<>nil) then
   begin
     CharToOemBuff(Buffer, Buf, Field.DataSize);
     Buffer:=@buf
   end;
  // pretend nativeformat is true
  inherited SetFieldData(Field, Buffer, True);
end;


Для полноценной работы с разными кодировками, как мне кажется, придется хорошенько порыться в исходнике.
Джентельмен
постоялец
Сообщения: 162
Зарегистрирован: 16.10.2005 10:47:26
Откуда: Украина Донбасс Краматорск
Контактная информация:

Сообщение Джентельмен »

э не батеньки...
так дело не пойдет...
функции большие тексты исходные...
вообщем кому интересно пишите мыло...
вышлю...
вообщем конвертит строку из KOI8-R в Win1251 и наоборот... и еще из cp866 в win1251 и наоборот... сам ими пользуюсь...
wellx
новенький
Сообщения: 67
Зарегистрирован: 06.05.2005 14:01:07

Сообщение wellx »

А может как-то с UTF-8 можно завязаться? Ну, чтобы потом не мучиться.
Аватара пользователя
STAKANOV
энтузиаст
Сообщения: 1069
Зарегистрирован: 14.05.2006 21:26:24
Откуда: Зеленоград

Сообщение STAKANOV »

А может как-то с UTF-8 можно завязаться? Ну, чтобы потом не мучиться.


Честно говоря мне лично сейчас не совсем понятно кто устанавливает стандарт (де факто) для DBF. Это же не изобретение сообщества OpenSource ;)

DBF вроде подерживается, но не не уверен, что развивается.

Что-то у нас спецы по БД молчат...
SAK
постоялец
Сообщения: 158
Зарегистрирован: 17.02.2006 23:45:14
Откуда: Тим
Контактная информация:

Сообщение SAK »

Мне кажется там и развиваться-то некуда, достоинство этого формата в его документированности и наличия большого количества программ для просмотра/редактирования и исправления ошибок. Кроме того надо писать программы и к уже существующим базам.

Если ближе к теме, то судя по документации в Delphi функция TDataset.Translate действительно предназначена для перекодировки строковых полей и вызывается из TStringField.GetValue. В Lazarus в TStringField такой вызов не предусмотрен, вот и получается функция есть, но не используется.
Что касается стандартов, то если в заголовке DBF по смещению 29 не указана кодировка, то подразумевается OEM, в противном случае указанная (например cp1251).
Аватара пользователя
STAKANOV
энтузиаст
Сообщения: 1069
Зарегистрирован: 14.05.2006 21:26:24
Откуда: Зеленоград

Сообщение STAKANOV »

Что касается стандартов, то если в заголовке DBF по смещению 29 не указана кодировка, то подразумевается OEM, в противном случае указанная (например cp1251).


хм...это меняет дело
я тут заглянул в исходники - в классе TDBF есть свойство CodePage:cardinal

Судя по описанию взятому мною с <a href='http://tdbf.sourceforge.net/' target='_blank'>http://tdbf.sourceforge.net/</a> он как раз и содержит значение кодовой страницы данных. Правда я еще пока не совсем понимаю как это можно использовать... :unsure:

но похоже автоматом оно точно не используется

и какие константы использовать как значения тоже не ясно... :unsure:
SAK
постоялец
Сообщения: 158
Зарегистрирован: 17.02.2006 23:45:14
Откуда: Тим
Контактная информация:

Сообщение SAK »

Я не знаю насколько эта информация верна, но некоторые коды упоминаются здесь <a href='http://www.gotdotnet.ru/Forums/Common/155460.aspx' target='_blank'>http://www.gotdotnet.ru/Forums/Common/155460.aspx</a>

А вот Database Desktop понимает следующие коды:
dBASE RUS cp866 = $26
Windows (ANSI) = $57
Alexey

Сообщение Alexey »

Две простые строки

dbfTarget.LanguageID := DbfLangId_RUS_866;
dbfTarget.TableLevel := 4;

где dbfTarget: TDbf;

а здесь возможные unit Dbf_Lang;
Аватара пользователя
STAKANOV
энтузиаст
Сообщения: 1069
Зарегистрирован: 14.05.2006 21:26:24
Откуда: Зеленоград

Сообщение STAKANOV »

Две простые строки


действительно ...

т.е. я должен сам прочитать/установить dbfTarget.LanguageID и в дальнейшем иметь это ввиду?
Ответить