TDbf и база с сайта ЦБ РФ

Общие вопросы программирования, алгоритмы и т.п.

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

TDbf и база с сайта ЦБ РФ

Сообщение qqqq1 » 20.08.2010 13:21:21

День добрый.

Проблема в следующем - TDbf не хочет открывать поля базы данных (пустота вместо данных), если ширина поля (в структуре таблицы) превышает 20. Как получить доступ к этим полям?
Сейчас просто меняю структуру в другой программе (уменьшаю длину поля) и тогда все OK.

Например, в TDBGrid (через TDbf) пустота вместо этого столбца.
Базу беру отсюда - http://www.cbr.ru/credit/transparent.asp (внизу страницы)

windows XP, Lazarus 0.9.28.2 / fpc 2.2.4
qqqq1
новенький
 
Сообщения: 12
Зарегистрирован: 20.08.2010 13:01:46

Re: TDbf и база с сайта ЦБ РФ

Сообщение Vadim » 20.08.2010 15:24:12

qqqq1
У меня отображаются. Поле name_b в таблице 062010N.dbf. Длина данных (почти в начале :) ) - 26 символов. Все их вижу.
Картинку можете поместить со своей проблемой?
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: TDbf и база с сайта ЦБ РФ

Сообщение qqqq1 » 20.08.2010 15:50:56

Уточнение.

Не открываются "числовые" поля. См., например, файлы 052010_B.DBF

Структура из программы DBFNavigator:
Поле ITOGO
тип numeric
ширина 33
дроб.часть 4
qqqq1
новенький
 
Сообщения: 12
Зарегистрирован: 20.08.2010 13:01:46

Re: TDbf и база с сайта ЦБ РФ

Сообщение Vadim » 23.08.2010 06:10:12

qqqq1
qqqq1 писал(а):Уточнение.

Не открываются "числовые" поля. См., например, файлы 052010_B.DBF

Вот это другое дело. :)
Я, птица-секретарь, даю справку ( :) ):
Maximum size of numeric and float fields........ 20

Это из самого прогрессивного, на сегодняшний момент, движка обработки файлов типа DBF - Microsoft Visual FoxPro.
У TDbf движок даже рядом с микрософтовским не валялся. Отсюда и глюк - то, что выходит за пределы предельно заданного размера не отображается.
Я думаю, ЦБР слегка погорячился с размерами этого поля. :) Вы можете, перед открытием файла для просмотра, поменять тип поля на ftString с соответствующим количеством символов в длине поля. Тогда данные в поле не пропадут и будут нормально отображаться.
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: TDbf и база с сайта ЦБ РФ

Сообщение qqqq1 » 23.08.2010 10:27:01

Спасибо за ответ.

Но проблема остаётся.
Дело в том, что я уже пытался поменять структуру (лежит на поверхности - просто думал, что можно что-то подправить в коде, чтобы заработало) - в частности уменьшить размер поля до 20. Собственно ничего не получается - процедура RestructureTable приводит к тому, что значения у поля обрезаются справа на 8 знаков. Например, было 14 988 290 582, стало 149. Причём глюк получается, даже если не менять структуру, а просто её скопировать.
Или у меня что-то не то с кодом?

Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
var
Dbf: TDbf;
FieldDefs: TDbfFieldDefs;
begin
  Dbf := TDbf.Create(nil);
  Dbf.TableName := 'C:\052010_B.DBF';
  Dbf.Open;
  FieldDefs := TDbfFieldDefs.Create(nil);
  FieldDefs.Assign(Dbf.DbfFieldDefs);
  Dbf.Close;
  //FieldDefs.Items[3].FieldType:=ftString;
  //FieldDefs.Items[3].Size:=20;
  Dbf.RestructureTable(FieldDefs, false);
  Dbf.Free;
  FieldDefs.Free;
end;
qqqq1
новенький
 
Сообщения: 12
Зарегистрирован: 20.08.2010 13:01:46

Re: TDbf и база с сайта ЦБ РФ

Сообщение Vadim » 23.08.2010 12:07:53

qqqq1
Тяжёлый случай... :) Значит TDbf категорически не воспринимает всё, что выходит за пределы его компетенции. В том числе и неправильный размер поля.
Тогда можно применить дедовский способ:
Код: Выделить всё
Type
  TDbfFieldR = packed record
    name: array[0..10] of char;
    FieldType: char;
    Place: DWord;
    Len: Byte;
    Dec: Byte;
    Flag: Byte;
    AutoInc: DWord;
    AutoIncStep: Byte;
    Reserved: array[0..7] of Byte;
  end;

procedure TForm1.FormCreate(Sender: TObject);
Var
  MyFile: TFileStream;
  fld: TDbfFieldR;
begin
  MyFile:=TFileStream.Create('062010_b.dbf', fmOpenReadWrite);
  MyFile.Seek(4*32, soFromBeginning);
  MyFile.Read(fld, SizeOf(TDbfFieldR));
  label1.Caption:=fld.name;
  MyFile.Seek(4*32, soFromBeginning);
  fld.FieldType:='C';
  MyFile.Write(fld, SizeOf(TDbfFieldR));
  MyFile.Free;
  dbf1.Open;
end;

Коротко суть:
DBF файл состоит из заголовка файла, который имеет размер 32 байта и некоторого кол-ва заголовков полей, которые тоже имеют размер по 32 байта. Тогда мы открываем файл в стандартном потоке, пропускаем заголовок файла и заголовки трёх полей (т.к. поле ITOGO у нас четвёртое по счёту). Далее, считываем заголовок четвёртого поля в переменную, меняем тип поля, подставляя соответствующую ему букву ("C" - CHARACTER) и записываем переменную обратно в файл на прежнее место. Закрываем файл-поток. Открываем его нашим несчастным TDbf... :)
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: TDbf и база с сайта ЦБ РФ

Сообщение qqqq1 » 23.08.2010 14:38:58

Спасибо!!!
Наконец заработало.

Но. Такой код “портит” заголовок таблицы – другие программы (например, DBFNavigator - в Lazarus всё OK) отказываются после этого читать такие файлы.
Решил добавлением своего кода. Как не странно, но после изменения типа и указания нового размера – всё работает.

Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
var
Dbf: TDbf;
FieldDefs: TDbfFieldDefs;
MyFile: TFileStream;
fld: TDbfFieldR;
begin
  MyFile:=TFileStream.Create('C:\052010_B.DBF', fmOpenReadWrite);
  MyFile.Seek(4*32, soFromBeginning);
  MyFile.Read(fld, SizeOf(TDbfFieldR));
  MyFile.Seek(4*32, soFromBeginning);
  fld.FieldType:='C';
  MyFile.Write(fld, SizeOf(TDbfFieldR));
  MyFile.Free;

  Dbf := TDbf.Create(nil);
  Dbf.TableName := 'C:\052010_B.DBF';
  Dbf.Open;
  FieldDefs := TDbfFieldDefs.Create(nil);
  FieldDefs.Assign(Dbf.DbfFieldDefs);
  Dbf.Close;

  FieldDefs.Items[3].FieldType:=ftFloat;
  FieldDefs.Items[3].Precision:=4;
  FieldDefs.Items[3].Size:=20;

  Dbf.RestructureTable(FieldDefs, true);
  Dbf.Free;
  FieldDefs.Free;
end;


Без Вашего кода просто стирает все значения поля.

Но осталась проблема. Код создаёт копию открываемого файла. Не критично, но неприятно.
qqqq1
новенький
 
Сообщения: 12
Зарегистрирован: 20.08.2010 13:01:46

Re: TDbf и база с сайта ЦБ РФ

Сообщение Nik » 16.11.2010 15:49:34

Столкнулся с похожей проблемой. Имеется файл DBF, слитый из 1С. При попытке открыть силами TDbf одно из полей (NAME, типа string) считывается в корявой кодировке (сама БД в кодировке Win-1251).
С такими БД дела до сих пор иметь не приходилось, ничего типа FoxPro под рукой нет, чтобы проверить, как там откроется.
В чём там ещё может быть заморочка?

Если что, файл здесь лежит.
Аватара пользователя
Nik
энтузиаст
 
Сообщения: 573
Зарегистрирован: 04.02.2006 00:08:09
Откуда: Киров

Re: TDbf и база с сайта ЦБ РФ

Сообщение Vadim » 16.11.2010 19:14:47

Nik
Кодовая страница - это 29-ый байт заголовка. У Вас там стоит $65, что означает ср866. Для ср1251 должно стоять $C9.
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: TDbf и база с сайта ЦБ РФ

Сообщение Nik » 16.11.2010 19:30:33

Не подскажете, как поправить, если нет возможности получить экспорт в другом виде?
Аватара пользователя
Nik
энтузиаст
 
Сообщения: 573
Зарегистрирован: 04.02.2006 00:08:09
Откуда: Киров

Re: TDbf и база с сайта ЦБ РФ

Сообщение Padre_Mortius » 16.11.2010 23:32:07

А конвертить сроку из одной кодировки в другую уже не принято? Примеров на этом форуме вроде бы достаточное количество. Например, тут можно посмотреть как это делается правильно
Padre_Mortius
энтузиаст
 
Сообщения: 1265
Зарегистрирован: 29.05.2007 17:38:07
Откуда: Спб

Re: TDbf и база с сайта ЦБ РФ

Сообщение Vadim » 17.11.2010 10:01:01

Nik
Nik писал(а):Не подскажете, как поправить, если нет возможности получить экспорт в другом виде?

Открываете файл как обычный поток или как файл произвольного доступа и записываете на место 29-ого байта (отсчёт начинается с нуля) шестнадцатиричную цифру $C9. Потом закрываете поток и можно пользоваться файлом. Можно воспользоваться любым HEX-редактором.
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: TDbf и база с сайта ЦБ РФ

Сообщение Nik » 17.11.2010 11:23:44

Padre_Mortius писал(а):А конвертить сроку из одной кодировки в другую уже не принято? Примеров на этом форуме вроде бы достаточное количество. Например, тут можно посмотреть как это делается правильно

Данные в файле лежат в правильной кодировке - win-1251. Но при загрузке в DBGrid вылазит черт-те что.
Vadim писал(а):Nik


Nik писал(а):Не подскажете, как поправить, если нет возможности получить экспорт в другом виде?

Открываете файл как обычный поток или как файл произвольного доступа и записываете на место 29-ого байта (отсчёт начинается с нуля) шестнадцатиричную цифру $C9. Потом закрываете поток и можно пользоваться файлом. Можно воспользоваться любым HEX-редактором.

Спасибо!
Аватара пользователя
Nik
энтузиаст
 
Сообщения: 573
Зарегистрирован: 04.02.2006 00:08:09
Откуда: Киров

Re: TDbf и база с сайта ЦБ РФ

Сообщение Vadim » 17.11.2010 13:42:57

Nik писал(а):Данные в файле лежат в правильной кодировке - win-1251. Но при загрузке в DBGrid вылазит черт-те что.

Это потому что кодировка в заголовке файла стоит неправильная. Ещё один камень в огород 1С. :D
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: TDbf и база с сайта ЦБ РФ

Сообщение Nik » 17.11.2010 16:00:39

Vadim писал(а):
Nik писал(а):Данные в файле лежат в правильной кодировке - win-1251. Но при загрузке в DBGrid вылазит черт-те что.

Это потому что кодировка в заголовке файла стоит неправильная. Ещё один камень в огород 1С. :D


Это я уже понял. Подозреваю, что можно как-то настроить экспорт в 1С, но пока нет возможности пообщаться с человеком, который за это отвечает. Так что буду править своими силами :)
Аватара пользователя
Nik
энтузиаст
 
Сообщения: 573
Зарегистрирован: 04.02.2006 00:08:09
Откуда: Киров

След.

Вернуться в Общее

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

Сейчас этот форум просматривают: Google [Bot] и гости: 16

Рейтинг@Mail.ru