1c логотип

Структура файла 1cv7.md

Введение

Есть так называемые контейнерные файлы: то есть файлы, содержащие внутри себя несколько файлов, которые к тому же могут быть разбиты по дереву подкаталогов. Примерами таких файлов могут служить практически все файлы MS Office. Кем-то совершенно случайно было обнаружено, что такой-же структурой обладают и файлы конфигурации 1С Предприятия - 1cv7.md. Для популярного файлового менеджера FAR существует плагин для просмотра и редактирования таких файлов, скачать который можно тут (32 Kb). Родина этого плагина находится по адресу www.7-zip.com

Для желающих получить более человечное представление внутренней структуры MD сделана утилита gcomp.

Общая структура файла 1cv7.md

  1. В каждом каталоге есть служебный файл Container.Contents, в котором описано, какие файлы и каталоги есть в текущей папке.
  2. Главный каталог, с которого 1С начинает рассмотрение md - Metadata. Там находится уже известный нам Container.Contents, TagStream, Main Metadata Stream и GUIDData.
    GUIDData
    содержит в себе информацию о наследовании файлов конфигурации. На содержание именно этого файла опирается 1с, когда говорит, что загружаемая конфигурация не является прямым потомком текущей. Почитать подробнее.
    Main Metadata Stream
    Содержит основную информацию о всех остальных элементах конфигурации Почитать подробнее.
    TagStream
    В этом потоке лежит все то, что находится в свойствах основного дерева метаданных на закладках "Автор" и "Заставка". То есть информация об авторе с логотипом, название конфигурации и ее заставка.

Подробнее о Main Metadata Stream

Этот файл разбит на множество секций, каждая из которых взята в фигурные кавычки. Секции могут быть вложенными. Внутри секции может находиться несколько параметров, разделенных запятыми. Секции одного вида имеют одинаковый набор параметров. Все секции имеют идентификаторы. Эти идентификаторы записаны в первом параметре любой секции. Если секция самого верхнего уровня, то она имеет текстовый идентификатор, обозначающий, какого типа метаданные описаны в этой секции. Например, у констант секция называется Consts, у справочников - SbCnts, у нумераторов документов - DocNumRef, и т. д. Если же секция содержит в себе описание какого-то конкретного объекта метаданных, то идентификатор, как правило, цифровой. Для тех объектов метаданных, которым можно сопоставить некий файл в базе данных, этот идентификатор совпадает с номером файла. Например, справочник "Номенклатура" в комплексной конфигурации имеет идентификатор 33 и файл sc33.dbf.

Рассмотрим строение секции на примере справочника "Номенклатура". Первым полем, как уже было сказано, является идентификатор. Вторым - тот идентификатор, который задан в конфигураторе. Далее идут комментарий и синоним, а так же другие параметры справочника, такие как длина кода, наименование, подчиненность, вид основного представления, и т. д.

Затем идет секция описания параметров, называется она "Param", и вся состоит из вложенных секций-параметров. В каждом параметре идет идентификатор, затем название в конфигураторе, комментарий с синонимом, тип данных (U-Неопределенный, N-Число, S-Строка, D-Дата, B-Справочник, O-Документ, E-перечисление, T-Счет, P-ПланСчетов, K-ВидСубконто, C-Календарь, A-ВидРасчета), и ряд параметров, характерных для данного типа данных (длина, неотрицательность, периодичность, индексация, и т. д.).

И последняя секция - секция форм списков ("Form"). Здесь описаны формы списка нашего справочника. В данной секции так же присутствуют числовой идентификатор формы списка, идентификатор с синонимом и комментарием, как задано в конфигураторе. Например в моей конфигурации, для формы списка "ФормаСписка" идентификатор 34, а для списка "ДляПодбора" - 549.

Подробнее о GUIDData

GUIDData - это поток, на основании которого 1С определяет, является ли загружаемая конфигурация прямым наследником текущей. Если в него вглядеться в процессе его изменения, то становится ясным, что при каждом сохранении в начало файла (со смещением 20) дописывается кусочек из 16-ти байт, а в конце те же 16 байт удаляются. То есть получается некое FIFO.

Из этого можно сделать несколько выводов.

Вывод первый. Если мы в конфигуратор загрузили (в режиме "загрузить измененную конфигурацию") конфигурацию А1, и нажали кнопку "Сохранить", то в результате мы получим уже другую конфигурацию (назовем ее Б1), которая будет отличаться от А1 составом потока GUIDData. Соответственно, если потом внести изменения в конфигурацию А1 (получим А2), и попытаться загрузить А2 в Б1, то мы получим сообщение о том, что "Загружаемая конфигурация не является потомком текущей".

Описываемый эффект часто возникает в ситуации, когда программист сидит дома и пишет конфигурацию, а раз в три дня приезжает к клиенту и загружает ее как измененную. Обычно подобный эффект вызывает изумление. В данном конкретном случае, разумеется, подобное сообщение можно игнорировать. Если же экспериментировать не хочется, то для избежания подобных сообщений сразу после создания конфигурации Б1 ее нуно загрузить поверх А1 (Получим В1), и уже дальнейшее редактирование производить в В1.

Вывод второй. При коллективной раработке с помощью GComp, поток GUIDData можно полностью игнорировать и не коммитить вообще. Ибо проблему уникальности идентификаторов метаданных при коллективной разработке решают другими способами. Однако можно и коммитить - хуже не будет. А вдобавок, если коммитить GUIDData, то по истории одного этого файла можно отследить все изменения, сделанные в конфигурации.

Вывод третий, на первый взгляд парадоксальный. Поскольку длина потока GUIDData ограничена (32020 байт), а как уже было сказано, ротация элементов в нем происходит по принципу FIFO, то становится очевидным, что после определенного числа сохранений (а именно (32020-20) / 16 = 2000) 1С перестает узнавать прямых потомков конфигурации.

Подробнее о справочнике "Номенклатура"

Справочник как метаданные - структура сложная. Наверное, в компенсацию за простоту хранения данных. :)

Метаданные для справочника, кроме файла Main Metadata Stream, находятся аж в трех папках. Это папки Subconto, SubFolder и SubList. Как можно легко понять из названий, там находятся формы элемента, группы и списков соответственно.

Внутри каждой папки находится куча папок с именами типа Subconto_NumberNNN, где NNN - идентификатор. Для папок Subconto и SubFolder идентификатор совпадает с идентификатором самого справочника, а для папки SubList у каждой формы списка свой идентификатор (указан в Main Metadata Stream). В дополнение скажу, что в каждой папке с номером-идентификатором, есть только одна подпапка WorkBook, в которой уже и находится то, что мы ищем.

Таким образом, описание формы элемента справочника "Номенклатура" можно найти в папке Subconto\Subconto_Number33\WorkBook. А форму списка "ДляПодбора" можно найти по пути SubList\SubList_Number549\WorkBook

Содержимое каждой папки WorkBook типовое. Она содержит максимум пять типов файлов.

  1. Уже знакомый нам Container.Contents
  2. Container.Profile. Его назначение мне неизвестно, появился он только в версии 7.7 и может вообще отсутствовать. Более того, даже если он есть, а мы его удалим, то конфигурация не потеряет работоспособности.
  3. Dialog Stream. Тут находится экранная форма. Просто нажмите F3 и посмотрите.
  4. MD Programm text. Здесь лежит модуль формы. По F3 посмотреть не получится - он запакован zip'ом с обрезанным заголовком. Для просмотра используем gcomp.
  5. Page.N. N - произвольное число, часто - 1 :). Печатная форма. Формат хранения - оригинальный от 1С. Если печатной таблицы в форме нет - файл отсутствует. Если печатных форм несколько - то и таких файлов будет несколько, различающиеся номерами. Пустая печатная форма обладает характерной длиной файла 147 байт (в 7.5 - 139).

Еще немного об общей структуре каталогов

Пройдемся теперь по всем каталогам и выясним их назначение. Внутри каждого каталога структура практически одинаковая: множество нумерованных подкаталогов, содержащих ту или иную часть метаданных. При этом номера соответствуют идентификаторам объектов из Main Metadata Stream.

Итак:

AccountChart
Тут лежат экранные формы счетов. Поскольку форма счета в конфигурации может быть только одна, то и поддиректория здесь тоже только одна. Всегда.
AccountChartList
Тут лежат экранные формы списка планов счетов.
CalcJournal
Экранные формы журналов расчетов.
CalcVar
Обработки.
Document
Документы. Тут все, кроме модуля проведения документа.
GlobalData
Общие таблицы.
Journal
Формы журналов документов.
Metadata
См. выше.
Operation
Экранная форма бухгалтерской операции.
OperationList
Экранные формы журналов операций.
Picture
Галерея картинок конфигурации.
ProvList
Экранные формы журналов проводок.
Report
Отчеты.
Subconto
Экранные формы элементов справочников.
SubFolder
Экранные формы групп справочников.
SubList
Экранные формы форм списков справочников.
TypedText
Эта директория сильно отличается от предыдущих. Тут находятся: Модули типов расчетов (каталоги CalcArg_Number*), Глобальный модуль (каталог ModuleText_Number1) Модули проведения документов (каталоги Transact_Number*), а так же описания всех объектов метаданных (каталоги UserHelp_Number*).
UserDef
Тут хранятся описания интерфейсов (папка Page.1) и наборы прав пользователей (папка Page.2). Формат хранения человеконечитаемый, пользуемся gcomp.

Зачем все это нужно?

У читающего все это может возникнуть резонный вопрос: а зачем все это нужно на практике, какое народо-хозяйственное значение? Разумеется, все не просто так.

Во-первых, кому-то просто может оказаться интересно: что же там понапихано в двенадцати (уже семнадцати) мегабайтах комплексной конфигурации? И, возможно, этот объем можно как-то уменьшить, не снижая функциональности?

Во-вторых, иногда, после каких-то сбоев, при попытке запустить 1С:Предприятие возникают ошибки с непонятной диагностикой навроде: C:\windows\temp\1cv7.md\Metadata\Main Metadata Stream - плохой путь. Теперь Вы хотя-бы понимаете, что это означает, и при удачном стечении обстоятельств можете битый 1cv7.md починить самостоятельно.

В-третьих, как оказывается, система защиты файла 1cv7.md паролем от чтения и записи не такая уж и абсолютная, как может показаться с первого взгляда.

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

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

Да и вообще, умный человек найдет применение данному знанию.

Как уменьшить размер файла 1cv7.md

Во-первых, надо четко понимать, что контейнерный файл - своеобразная база данных. А базы данных имеют обыкновение хранить в себе пустые места. Например, в dbf удаленные записи не удаляются, а освобождаются для последующих записей. md - не dbf, но и в нем при определенных действиях возникают "дырки".

Сохранение файла 1cv7.md может происходить двума способами. Простое сохранение без лишних вопросов происходит, если изменения коснулись только в модулей, а так же печатных и экранных форм. Сохранение с анализом изменений и возможной реорганизацией БД происходит в тех случаях, когда она предполагает изменение структуры данных. Простейший способ этого добиться, не изменяя конфигурацию - добавить и тут же удалить новую константу или реквизит любого справочника/документа. Можно так же зайти в свойства любого реквизита или объекта, и в комментарии добавить и тут же удалить пробел (я именно так и делаю).

Так вот: только после сохранения с анализом изменений мы можем получить 1cv7.md минимального размера для текущей функциональности.

Иногда мне кажется, что я не всегда внятно излагаю :), поэтому вот тут можно посмотреть описание того же эффекта другими людьми.

Вместо сохранения измененной конфигурации - можно еще перепаковать конфигурацию gcomp'ом


Во-вторых, как уже было сказано чуть выше, присутствие или отсутствие файлов container.profile никак не влияет на функциональность конфигурации. Соответственно, мы можем удалить все такие файлы с помощью плагина к FAR'у, потом загрузить получившуюся конфигурацию как измененную, сохранить, и получить выигрыш по 512 байт на каждый такой файл.

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

Если вам лень перебирать ручками все папки в поисках потоков Container.Profile - воспользуйтесь утилитой gcomp, и с ее помощью перепакуйте конфигурацию с ключом --no-profiles.


В-третьих, после вдумчивого рассмотрения всех каталогов, я обнаружил одну забавную особенность каталога Journal. В нем оказались каталоги с идентификаторами, для которых не существует форм журналов. Однако, эти идентификаторы порой совпадали с идентификаторами самих журналов. Вероятно, еще в версии 7.0 (я знаком с ней весьма поверхностно, поэтому не могу утверждать наверняка), журналы документов могли иметь только одну форму списка. Очевидно, что эта форма имела тот же идентификатор, что и сам журнал. Когда же в версии 7.5 появилась возможность заводить несколько форм для одного журнала, идентификаторы форм, очевидно, пришлось поменять. Однако при преобразовании конфигурации из старого формата "старые" формы, видимо, забыли удалить. Эти формы можно легко опознать по идентификатору - они все меньше 900. В качестве дополнительного подтверждения того, что эти каталоги абсолютно излишни на текущий момент, могу указать на то, что в соответствующем Container.Contents из каталога Journal нет ни одного упоминания о том, что такие папки должны присутствовать.

В комплексной 2.6 таких "забытых" форм 13 штук. Если учесть, что каждая состоит как минимум из пяти файлов и одного каталога, то нетрудно посчитать, что их удаление принесет нам 6 * 13 * 512 = килобайт 40 как минимум. А за счет того, что экранные формы меньше трех кластеров почти никогда не занимают, реальный выигрыш наверняка окажется вдвое значительнее.

И здесь поможет перепаковка конфигурации gcomp'ом. И даже никаких опций не нужно.


Более детальное исследование экранных форм показало, что для каждого объекта на форме хранится название того слоя, которому этот элемент принадлежит. По умолчанию, название единственного слоя - "Основной". Если слой один, а объектов на форме два десятка, то постым переименованием слоя в "О", можно добиться экономии 7 * 20 = 140 байт. И если повезет, форма станет занимать на один 512-ти байтный блок меньше. Если Вам кажется, что это мелочь - вспомните, сколько экранных форм в конфигурации.

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


Вспомним о пустых таблицах. Они занимают один кластер, то есть, 512 байт. Просто удивительно, насколько их много, особенно в формах журналов, обработках и формах списков справочников (то есть там, где они абсолютно не нужны).

И здесь у gcomp'а нашлась опция. --no-empty-mxl называется.


Что касается справочников. У справочника, как мы помним, есть аж три формы: списка, группы и элемента. Так вот, если в справочнике один уровень, то форма группы, очевидно, не нужна. Если справочник редактируется только в списке, то не нужна еще и форма элемента. И если первую ситуацию 1С отслеживает и предлагает удалить неиспользуемую форму группы, то ненужную форму элемента не только нельзя удалить штатными способами, но она еще и автоматически будет создана при первой попытке в нее войти (что-то MS запахло, не правда ли?). Удалить такую форму можно только хирургически, читай, с помощью плагина DocFile Browser. Главное, не забыть удалить ссылку на удаленный каталог в Subconto\Container.Contents

Данная тонкая хирургия gcomp'у неподвластна.


Еще одно поле для деятельности - картинки. Для gcomp'а создан скрипт (show_pics), который показывает статистику по используемым (и главное - по неиспользуемым) картинкам. А картинки могут быть большими, очень большими, и воистину огромными.


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

 
истории, анекдоты, картинки, фотоприколы...
  © 1c для чайников, 2005-2006