Динамическое создание структуры RECORD
Модератор: Модераторы
Если речь идёт о компоненте не связанном с SQLDb, то, я думаю, можно создать класс наследник от TDataSet, в котором и определять динамически поля.
Примерный (
) механизм:
1. Читаем файл *.BTR в поток.
2. Считываем из потока информацию о структуре таблицы.
3. Создаём динамически в наследнике TDataSet аналогичную структуру.
4. Перебрасываем данные из потока в наследника...
Добавлено спустя 3 минуты 38 секунд:
GrayEddy

Примерный (
1. Читаем файл *.BTR в поток.
2. Считываем из потока информацию о структуре таблицы.
3. Создаём динамически в наследнике TDataSet аналогичную структуру.
4. Перебрасываем данные из потока в наследника...
Добавлено спустя 3 минуты 38 секунд:
GrayEddy
- bloodlines
- постоялец
- Сообщения: 100
- Зарегистрирован: 05.11.2008 10:26:19
2. Считываем из потока информацию о структуре таблицы.
Это не в BTR а в DDF или другом файле словаря храниться. Автоматическое определение полей пока не входит в мои цели.
3. Создаём динамически в наследнике TDataSet аналогичную структуру.
На данный момент это единственное что мне нужно.
Я использую API из Pervasive SDK. И просто оборачиваю это во что то немного более удобное...
bloodlines
Тогда всё предельно просто. Если есть нормальный файл словоря (с известной структурой файла
), то считывать информацию о структуре таблицы из него и создаём в наследнике аналогичную структуру.
Тогда всё предельно просто. Если есть нормальный файл словоря (с известной структурой файла
- bloodlines
- постоялец
- Сообщения: 100
- Зарегистрирован: 05.11.2008 10:26:19
Для чтения (позиционирования) из BTR файла используется функция
Где dataBuffer - структура PACKED RECORD в которую заноситься значения полей текущей записи, keyBuffer - структура PACKED RECORD, описывающая постоянную (индексную) часть BTR файла.
Не думаю, что вместо dataBuffer можно поставить например MemDataset1.Fields...
Вся суть задачи заключается в удобном определении полей и чтении данных, остальное для меня пока не критично.
Код: Выделить всё
FUNCTION BTRVID(
operation : WORD;
VAR positionBlock;
VAR dataBuffer;
VAR dataLen : WORD;
VAR keyBuffer;
keyNumber : SMALLINT;
VAR clientID ) : SMALLINT;Где dataBuffer - структура PACKED RECORD в которую заноситься значения полей текущей записи, keyBuffer - структура PACKED RECORD, описывающая постоянную (индексную) часть BTR файла.
Не думаю, что вместо dataBuffer можно поставить например MemDataset1.Fields...
Вся суть задачи заключается в удобном определении полей и чтении данных, остальное для меня пока не критично.
bloodlines писал(а):Не думаю, что вместо dataBuffer можно поставить например MemDataset1.Fields...
Ну ясен перец.
У Вас Вы будете выдёргивать определённое кол-во байтов с той позиции, которые указаны в структуре полей.
- bloodlines
- постоялец
- Сообщения: 100
- Зарегистрирован: 05.11.2008 10:26:19
У меня сейчас суть вопроса в том, что поставить вместо dataBuffer.
1. Берешь MemDataSet1, куда загнал структуру, она может включать: имя поля, длина в байтах, и т.д.
1. В dataBuffer ставишь указатель на начало буфера.
Тут идет цикл
2. Считываешь первое поле из MemDataSet, узнаешь длину в байтах.
3. Читаешь из dataBuffer ... байт, которые считал из пункта 2. При необходимости приводишь к нужному типу. Тип можно считать из п. 2
4. Снова идешь на п. 2 и читаешь следующее поле. Потом снова п.3. И так далее, пока не обойдешь все поля в MemDataSet1, и не прочтешь весь dataBuffer.
PS. Размер dataBuffer должна совпасть с размером всех полей, входящих в MemDataSet1. Это так, для проверки.
1. В dataBuffer ставишь указатель на начало буфера.
Тут идет цикл
2. Считываешь первое поле из MemDataSet, узнаешь длину в байтах.
3. Читаешь из dataBuffer ... байт, которые считал из пункта 2. При необходимости приводишь к нужному типу. Тип можно считать из п. 2
4. Снова идешь на п. 2 и читаешь следующее поле. Потом снова п.3. И так далее, пока не обойдешь все поля в MemDataSet1, и не прочтешь весь dataBuffer.
PS. Размер dataBuffer должна совпасть с размером всех полей, входящих в MemDataSet1. Это так, для проверки.
- bloodlines
- постоялец
- Сообщения: 100
- Зарегистрирован: 05.11.2008 10:26:19
GrayEddy спасибо!
Не совсем понял мысль... dataBuffer по документации должна быть структура PACKED RECORD.
1. В dataBuffer ставишь указатель на начало буфера.
Не совсем понял мысль... dataBuffer по документации должна быть структура PACKED RECORD.
bloodlines писал(а):VAR dataBuffer
А Вы не ошибаетесь? Судя по этому:
Код: Выделить всё
VAR dataBufferтам как раз нужен безтиповой параметр. На его место можете подставлять всё, что хотите.
- bloodlines
- постоялец
- Сообщения: 100
- Зарегистрирован: 05.11.2008 10:26:19
Извиняюсь - туплю...
Ещё пара ламерских вопросов
1 - Как считать нужное количество байт из databuffer, должна быть какая то функция, но я не помню.
2 - Как привести результат чтения к нужному типу?
Ещё пара ламерских вопросов
3. Читаешь из dataBuffer ... байт, которые считал из пункта 2. При необходимости приводишь к нужному типу. Тип можно считать из п. 2
1 - Как считать нужное количество байт из databuffer, должна быть какая то функция, но я не помню.
2 - Как привести результат чтения к нужному типу?
Код: Выделить всё
var P: Pointer
...
GetMem(P, размер_структуры);
...
Добавлено спустя 1 минуту 21 секунду:
1. Move(...)
2. Для этого желательно знать тип поля.
Добавлено спустя 7 минут 10 секунд:
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=624
Структура DBF-файлов для непродвинутых
Хорошая статья, достаточно посидеть час и все прояснится. У Вас примерно такая же задача по смыслу.
1. Узнать структуру для чтения файла.
2. Зная структуру - читаем данные
Это очень сложный путь. Проще обойтись динамическим массивом
TDynamicStringArray=array of string;
var
mybase:array of TDynamicStringArray;
Далее, считаешь количество полей, заносишь в mybase[0][i] названия
в остальные строки - по мере поступления.
Да, не забываем SetLength использовать....
TDynamicStringArray=array of string;
var
mybase:array of TDynamicStringArray;
Далее, считаешь количество полей, заносишь в mybase[0][i] названия
в остальные строки - по мере поступления.
Да, не забываем SetLength использовать....
- bloodlines
- постоялец
- Сообщения: 100
- Зарегистрирован: 05.11.2008 10:26:19
Уважаемый, GrayEddy...
Я так понял, P ставим на место DataBuffer. В сущности, поскольку перед DataBuffer стоит параметр Var это означает, что в функцию BTRVID передаётся на сама переменная, а указатель на область памяти, в которой она храниться. То же самое после указанного кода представляет собой P.
А как занести в область памяти на которую ссылается указатель P значение некоторой переменной причём в определённый участок памяти. Это понадобиться для операций обновления записи и добавления новой записи а так же для работы с индексами.
В одном из примеров индекс описан так
Как выделить память мне понятно, но как занести в область памяти значение переменной...? В данном случае аналог
Код: Выделить всё
var P: Pointer
...
GetMem(P, размер_структуры);
...Я так понял, P ставим на место DataBuffer. В сущности, поскольку перед DataBuffer стоит параметр Var это означает, что в функцию BTRVID передаётся на сама переменная, а указатель на область памяти, в которой она храниться. То же самое после указанного кода представляет собой P.
А как занести в область памяти на которую ссылается указатель P значение некоторой переменной причём в определённый участок памяти. Это понадобиться для операций обновления записи и добавления новой записи а так же для работы с индексами.
В одном из примеров индекс описан так
Код: Выделить всё
OPERHEAD_INDEX7 = packed record
appIsn : longint;
appName : array[0..8] of char;
end;
var
OperHeadIndex7 : OPERHEAD_INDEX7; {индекс номер 7}
OperheadIndex0.appIsn := 8 AsInteger; {присвоение параметров поиска}
fillchar(OperheadRecord , SizeOf(OperheadRecord), #0);
dataLen := sizeof(OPERHEAD_STRUCT);
status := BTRVID(B_GET_EQUAL, {системная константа}
PosBlock, {системная}
OperheadRecord, {сюда будет возвращен результат поиска}
dataLen, {см.выше}
OperheadIndex7, {см.выше}
7, {номер индеска - см.выше}
client); {системная}
Как выделить память мне понятно, но как занести в область памяти значение переменной...? В данном случае аналог
Код: Выделить всё
OperheadIndex0.appIsn := 8 AsInteger;Сведений недостаточно.
Вышлите мне на почту btr-файл(ы) и документацию (или ссылки) по структуре этих файлов, посмотрю.
Вышлите мне на почту btr-файл(ы) и документацию (или ссылки) по структуре этих файлов, посмотрю.
