Краткое описание формата файлов *.1CD (файловых баз 1Сv8)

После того, как я выложил свою программку Tool_1CD ( http://infostart.ru/projects/3851/ ), оказалось, что интерес к формату файлов 1CD достаточно велик. Поэтому для всех желающих продолжить разбираться с форматом, или желающих написать свою программу, выкладываю свои текущие знания об этом формате.

После того, как я выложил свою программку Tool_1CD ( http://infostart.ru/projects/3851/ ), оказалось, что интерес к формату файлов 1CD достаточно велик. Поэтому для всех желающих продолжить разбираться с форматом, или желающих написать свою программу, выкладываю свои текущие знания об этом формате.

Описание формата приведено в терминах языка C. Размер типа char – 1 байт, размер типа short int – 2 байта, размер типа int и unsigned int – 4 байта. Префиксом 0x обозначаются шестнадцатеричные числа.

Файлы баз *.1CD состоят из блоков длиной 4096 байт (0x1000). Соответственно, длина файла всегда кратна 4096.

Блок 0

Нулевой блок имеет следующую структуру:

struct {

char sig[8]; // сигнатура “1CDBMSV8”

char ver1;

char ver2;

char ver3;

char ver4;

unsigned int length;

int unknown;

}

Первые 8 байт – сигнатура базы «1CDBMSV8».

Следующие 4 байта - это версия базы. На данный момент мне встречались только версия «8.0.5.0» (ver1 = 8, ver2 = 0, ver3 = 5, ver4 = 0) – это базы 1Cv8.0 и версия «8.1.0.0» (ver1 = 8, ver2 = 1, ver3 = 0, ver4 = 0) – это базы 1Cv8.1 и 1Cv8.2.

Следующие 4 байт – длина базы (файла) в блоках.

Предназначение поля unknown неизвестно, всегда содержит 1.

Объекты

Вся остальная информация в базе хранится в объектах (файлах базы). Каждый объект состоит из одного или более блоков. У каждого объекта есть один заголовочный блок, блоки с таблицей размещения, и собственно данные. Второе и третье может отсутствовать.

Структура первого блока каждого объекта такова:

struct {

char sig[8]; // сигнатура “1CDBOBV8”

int length; // длина содержимого объекта

int version1;

int version2;

unsigned int version;

unsigned int blocks[1018];

}

Первые 8 байт – сигнатура базы «1CDBOBV8».

Есть 2 типа объектов.

Блок 1. Таблица свободных блоков

Первый тип объекта – это таблица свободных блоков. Признаком этого блока является поле version равное 0. Такой объект в базе всегда один, и его заголовочный блок располагается всегда в блоке со смещением 1 (т.е. по адресу 0x1000). Длина данных такого объекта равна (length * 4) байт.

В blocks содержатся номера блоков, в которых собственно и находится содержимое таблицы свободных блоков. Значащими являются ненулевые значения в массиве blocks. Содержимое таблицы свободных блоков – это просто массив номеров свободных блоков:

unsigned int free_blocks[length];

Таким образом, в базе содержатся ровно length свободных блоков.

Когда системе требуется новый блок для данных, то она берет последний свободный блок из массива free_blocks и уменьшает length на 1. Если свободных блоков нет, то он создается в конце файла базы. Блоки, содержащиеся в массиве blocks, не являются свободными, а принадлежат объекту – таблице свободных блоков. В blocks может содержаться больше блоков, чем необходимо для хранения массива free_blocks.

Остальные объекты

Второй тип объектов характеризуется ненулевым значением поля version. Вся информация в базе, кроме блока 0 и таблицы свободных блоков хранится именно в таких объектах.

В поле length содержится длина в байтах данных объекта.

В массиве blocks находятся индексы блоков, содержащих таблицу размещения данных объекта. Каждый блок, указанный в blocks, и являющийся частью таблицы размещения, имеет следующую структуру:

struct {

int numblocks;

unsigned int datablocks[1023];

}

Поле numblocks указывает количество реальных значений в datablocks (от 1 до 1023). В datablocks содержатся индексы блоков, в которых находится собственно содержимое объекта (данные). Так как в одном блоке таблицы размещения может быть указано максимум 1023 блока с данными, то соответственно, максимальная длина данных, указанных в одном блоке таблицы размещения равна 1023 * 4096 = 4190208 байт (0x3ff * 0x1000 = 0x3ff000). Таким образом, из длины содержимого объекта length мы можем определить количество фактических значений в blocks. Если length равен 0, то в blocks нет значащих данных, иначе количество значений в blocks равно (length - 1) / 0x3ff000 + 1 (деление целочисленное, без остатка). А также можно вычислить максимальную длину данных одного объекта: 4190208 * 1018 = 4265631744 байт (1018 – максимальное количество значений в массиве blocks), это совсем немного меньше 4х гигабайт.

Повторим, в заголовочном блоке объекта находится массив blocks, содержащий индексы блоков с таблицей размещения. А в таблице размещения находятся блоки, содержащие сами данные.

Блок 2. Корневой объект

Последним объектом с предопределенным расположением является корневой объект. Заголовочный блок корневого объекта располагается в блоке с индексом 2. Все остальные объекты базы могут быть получены через корневой объект. Структура данных этого объекта зависит от версии базы, хотя и различается несильно. Для версии базы «8.0.5.0» эта структура выглядит так:

struct {

char lang[8];

int numblocks;

int tableblocks[numblocks];

}

Для версии «8.1.0.0» структура выглядит так:

struct {

char lang[32];

int numblocks;

int tableblocks[numblocks];

}

Т.е. различаются эти структуры только длиной поля lang. В поле lang содержится код языка базы. Код языка базы представляет собой строку в ANSI-кодировке. Мне встречались только базы с кодами «ru_RU» и «en». На что влияют эти коды языка, я не знаю, возможно, на порядок сортировки строк при построении индексов.

В поле numblocks содержится количество элементов в массиве tableblocks. В массиве же tableblocks содержатся индексы объектов, содержащих все таблицы данных. Т.е. таблиц в базе ровно numblocks.

Объект таблицы

Каждый объект таблицы, указанный в корневом объекте, содержит просто текстовое описание таблицы в Unicode. Вот пример описания таблицы:

{"_Reference4",0,

{"Fields",

{"_IDRREF","B",0,16,0,"CS"},

{"_VERSION","RV",0,0,0,"CS"},

{"_MARKED","L",0,0,0,"CS"},

{"_ISMETADATA","L",0,0,0,"CS"},

{"_CODE","NC",0,9,0,"CI"},

{"_DESCRIPTION","NVC",0,25,0,"CI"},

{"_FLD7","I",1,0,0,"CS"}

},

{"Indexes",

{"_IDRREFIDX",1,

{"_IDRREF",16}

},

{"_REFERENCE4_CODE_SR",0,

{"_CODE",9},

{"_IDRREF",16}

},

{"_REFERENCE4_DESCR_SR",0,

{"_DESCRIPTION",25},

{"_IDRREF",16}

}

},

{"Recordlock","0"},

{"Files",118,119,96}

}

Как видно из этого примера, здесь присутствуют имя таблицы (_Reference4), раздел описания полей таблицы (Fields), раздел описания индексов (Indexes), параметр Recordlock и раздел Files.

В разделе Files всегда содержатся три числа, которые содержат индексы заголовочных блоков объектов (по порядку) с записями таблицы, Blob-данными (строки неограниченной длины и двоичные данные) и индексами. Если какого-либо объекта у таблицы нет, то соответствующее число равно нулю.

В разделе Fields содержатся описания полей таблицы. Описание каждого поля содержит (по порядку): имя поля (FieldName), тип поля (FieldType), признак использования NULL (NullExists), длину (FieldLength), точность (FieldPrecision) и признак регистрочувствительности (FieldCaseSensitive).

Сколько байт занимает каждое поле в записи, и как его интерпретировать, зависит от параметров поля. Во-первых, если NullExists у поля равен 1, то первый байт поля является признаком NULL. Значение 0 этого байта означает, что поле не содержит значение (т.е. содержит NULL). В противном случае, поле содержит значение. Если же NullExists равен 0, то такого байта в поле нет.

Далее, размер и формат поля зависит от типа поля. Типы поля бывают такими:

  • «B» - двоичные данные. Длина поля равна FieldLength байт.
  • «L» - булево. Длина поля 1 байт. Нулевое значение байта означает Ложь, иначе Истина.
  • «N» - число. Длина поля в байтах равна Цел((FieldLength + 2) / 2). Числа хранятся в двоично-десятичном виде. Первый полубайт означает знак числа. 0 – число отрицательное, 1 – положительное. Каждый следующий полубайт соответствует одной десятичной цифре. Всего цифр FieldLength. Десятичная точка находится в FieldPrecision цифрах справа. Например, FieldLength = 5, FieldPrecision = 3. Байты 0x18, 0x47, 0x23 означают число 84.723, а байты 0x00, 0x00, 0x91 представляют число -0.091.
  • «NC» - строка фиксированной длины. Длина поля равна FieldLength * 2 байт. Представляет собой строку в формате Unicode (каждый символ занимает 2 байта).
  • «NVC» - строка переменной длины. Длина поля равна FieldLength * 2 + 2 байт. Первые 2 байта содержат длину строки (максимум FieldLength). Оставшиеся байты представляет собой строку в формате Unicode (каждый символ занимает 2 байта).
  • «RV» - версия. Длина поля 16 байт. Предположительно содержит четыре числа int.
  • «NT» - строка неограниченной длины. Длина поля 8 байт. Первые четыре байта содержат начальный индекс блока в объекте Blob таблицы, вторые четыре – длину данных в объекте Blob. В объекте Blob содержится строка в формате Unicode.
  • «I» - двоичные данные неограниченной длины. Длина поля 8 байт. Первые четыре байта содержат начальный индекс блока в объекте Blob таблицы, вторые четыре – длину данных в объекте Blob.
  • «DT» - дата-время. Длина поля 7 байт. Содержит данные в двоично-десятичном виде. Первые 2 байта содержат четыре цифры года, третий байт – две цифры месяца, четвертый байт – день, пятый – часы, шестой – минуты и седьмой – секунды, все также по 2 цифры.

Зная теперь длину в байтах каждого поля можно посчитать общую длину одной записи таблицы и смещение каждого поля в записи. Но для этого необходимо учесть следующее. Если в описании полей таблицы нет поля с типом версия (RV), но при этом параметр Recordlock равен 1, то в записи присутствует дополнительное поле, которое я для себя называю короткая скрытая версия. Длина этого поля равна 8 байт. В каждой записи самый первый байт – это признак удаленности записи (признак, что запись не занята). Если этот байт равен 1, то запись свободна, а следующие 4 байта содержат индекс следующей свободной записи. Из этого следует, что запись не может быть короче пяти байт. Если же первый байт записи содержит 0, то далее в записи следуют значения полей. Причем порядок полей определяется таким образом: превым всегда идет поле версии (или описанное в разделе Fields с типом RV или поле скрытой короткой версии), затем все остальные поля в том порядке, как они описаны в разделе Fields.

Объект записей таблицы

Содержимое объекта записей таблицы содержит просто массив записей. Таким образом, длина данных этого объекта всегда кратна длине одной записи. Первая (точнее нулевая) запись всегда помечена как свободная, она содержит индекс следующей свободной записи (или 0, если таких нет). Т.е. с нее начинается цепочка свободных записей таблицы.

Объект Blob таблицы

Объект содержит Blob-данные таблицы (строки неограниченной длины и двоичные данные неограниченной длины). Содержимое этого объекта состоит из блоков (не путать с блоками, из которых состоит файл 1CD) длиной 256 байт (0x100). Т.е. это просто массив блоков длиной 256 каждый. Поэтому длина данных объекта всегда кратна 256. Структура каждого блока объекта такова:

struct {

unsigned int nextblock;

short int length;

char[250] data;

}

Поле nextblock содержит индекс следующего блока, содержащего продолжение данных, или 0, если следующего блока нет. Поле length содержит длину данных в этом блоке (максимум 250). Поле data содержит сами данные. Нулевой блок всегда считается свободным, в поле nextblock он содержит индекс следующего свободного блока. Таким образом, с нулевого блока начинается цепочка свободных блоков.

В записях таблицы в полях с типом «NT» и «I» содержится индекс первого блока, с которого начинаются данные, относящиеся к этому полю данной записи.

Объект индексов таблицы

На данный момент структура индексов до конца не изучена.

Начать дискуссию

Общество

👍 Президент подписал закон, упрощающий принятие решений на общих собраниях членов СНТ и ОНТ

Владимир Путин подписал разработанный при участии Росреестра федеральный закон, которым упрощен процесс принятия решений на общих собраниях членов садоводческих (СНТ) и огороднических товариществ.

Патентная активность российских изобретателей выросла на 7%

Более 15 000 заявок на патентование изобретений и полезных моделей подали отечественные разработчики в Федеральную службу по интеллектуальной собственности (Роспатент) с января по июнь 2024 года.

Опубликованы поручения Президента по итогам Петербургского международного экономического форума-2024

Владимир Путин утвердил перечень поручений по итогам ПМЭФ-2024, который прошел 5–8 июня.

Курсы повышения
квалификации

18
Официальное удостоверение с занесением в госреестр Рособрнадзора

Нацбюро кредитных историй назвало средний размер автокредита

По данным кредиторов, передающих сведения в Национальное бюро кредитных историй (НБКИ), в июне 2024 года средний размер выданных автокредитов составил 1,47 млн рублей.

МВД: если поменяли сим-карту, открепите номер от Госуслуг и мобильного приложения

Киберпреступники приобретают старые сим-карты, которые уже были использованы и поступили в повторную продажу.

1
УК РФ

Ответственность за цифровые преступления ужесточат

По результатам деятельности созданной в 2020 году на площадке Генпрокуратуры межведомственной рабочей группы подготовлены проекты федеральных законов об ужесточении ответственности за преступления в цифровой среде.

Опытом делятся эксперты-практики, без воды

Как разработать детальный финансовый план и бюджет для бизнеса

Разработка детального финансового плана и бюджета — ключевой аспект успешного управления бизнесом. Этот процесс помогает предусмотреть финансовые трудности и эффективно распределить ресурсы, обеспечивая устойчивое развитие компании. В данном руководстве вы найдете пошаговый план для создания финансового плана и бюджета.

Инвестиции

Пополнил брокерский счет на 300 000 в июле. Что купил? Часть 2

Заканчивается июль, а вместе с ним и бюджет, который был выделен на инвестиции. В первой половине месяца я покупал чуть меньше акции, чуть больше облигации, а также немного фондов. Во второй половине месяца действовал примерно по тому же плану.

Пополнил брокерский счет на 300 000 в июле. Что купил? Часть 2

Новые функции и улучшения на «Клерке»: обновления за июль. Выпуск #1

В июле представили обновления: сортировка главной страницы одним кликом, новый инструмент для самозанятых, возможность монетизации для авторов в "Трибуне" и продвижение материалов в блогах компаний. Также улучшен сервис "Клерк.Работа" и введены новые функции для Бизнес Аккаунта и личного кабинета.

Новые функции и улучшения на «Клерке»: обновления за июль. Выпуск #1
2
Обзоры новостей

Налог на бездетность, Ивлеева уплатила долг, НДФЛ при манипуляциях с землей в обзоре

Интересные события в налоговой сфере.

Бухгалтеры не видят актуальных данных ЕНС и не могут сформировать электронные подписи в ЛК. 🔨«Ночной бухгалтер» № 1733

Никогда такого не было... Бухгалтеры жалуются, что в личных кабинетах невозможно посмотреть актуальную информацию по сальдо ЕНС. Данные стоят на 15, 18, 19 июля. Если написать через ЛК налоговикам, сведения обновляются, но не всем. Формировать электронные подписи многие также не могут, не отправить 3-НДФЛ, не обновить электронные подписи.

Иллюстрация: Вера Ревина/Клерк.ру
Инвестиции

Физлицам и компаниям ЕС запретили участвовать в российской схеме обмена активами

Власти Евросоюза призвали инвесторов и компании не участвовать в обмене заблокированных ценных бумаг, поскольку в этом механизме участвует подсанкционный Национальный расчетный депозитарий.

ОСАГО

ОСАГО можно оформить онлайн через Сбер

Водители могут застраховать машину онлайн за несколько минут. Достаточно ввести данные документов и выбрать страховщика на маркетплейсе Сбербанка.

Для россиян тоже установят лимит на количество сим-карт

Несколько сим-карт нужны владельцам гаджетов, которые позволяют управлять умным домом и камерами наблюдения.

Сотрудников не могут заставить сдавать отпечатки пальцев

Частные компании не имеют права проводить дактилоскопическую регистрацию сотрудников, чтобы наладить пропускной режим на объекте.

Бухгалтеры

НДС на УСН в 2025 году, выбор налогового режима, топ претензий от ФНС, и господдержка бизнеса — какие вебинары пройдут в августе 2024 года

Подготовили для вас анонс предстоящих вебинаров в августе.

НДС на УСН в 2025 году, выбор налогового режима, топ претензий от ФНС, и господдержка бизнеса — какие вебинары пройдут в августе 2024 года
Новости ФНС

ФНС начнет регистрировать личные фонды россиян

Полномочия по регистрации личных фондов для управления бизнесом, имуществом и активами перешли от Минюста к ФНС.

Личные финансы

Цены на туры в Турцию выросли до 300 000 рублей за среднюю путевку

Итоги первой половины лета показали, что отдых на море в этом году стал для россиян дороже еще на несколько десятков процентов. Подорожало все — и гостиницы, и перелеты, и пакетные туры. Причем не только за границей, но и в России.

Бесплатно с Трудовое право

Трудовые споры: сколько денег можно взыскать с работодателя за неправильную запись в трудовой книжке 

Все зависит от того, в состоянии ли работник доказать, что неправильная запись в трудовой лишила его заработка. Разбираем детали.

Трудовые споры: сколько денег можно взыскать с работодателя за неправильную запись в трудовой книжке 

Интересные материалы

Кадровый учет

Перемещение работника

В данном материале рассмотрим, как выглядит процедура перемещения сотрудника. Поговорим о том, какими документами оформляется это кадровое мероприятие. Разберем, в чем состоят отличия между перемещением и переводом работника.

Иллюстрация: Вера Ревина/Клерк.ру