Описание на формата на конфигурационния файл (CF, EPF, ERF)
Вътрешната структура на конфигурационния файл (*.cf) не е тайна. Любезните хора го разглобиха отдавна и създадоха много интересни помощни програми, които ви позволяват да работите с този формат. В Infostart има дузина (ако не и повече) интересни публикации, които четат съдържанието на *.cf файлове по един или друг начин, така че тази тема изобщо не е нова.
Въпреки това, за съжаление, има много малко добра, солидна документация за този формат. За да напиша тази статия, бях вдъхновен от публикацията на високо уважавания awa, който описа подробно, във всички подробности, структурата на файловия формат 1C:Enterprise IS (*.1CD).
заден план
Както споменахме по-горе, структурата на формата е известна отдавна и има информация за нейната структура в мрежата (макар и доста оскъдна). Имах нужда от тази информация при разработването на програмата V8Viewer, работейки върху която, разчитах на следните материали:
Терминология
Да преминем директно към темата на нашата дискусия.
За да поставим точката на i, нека дефинираме името на самия формат.
Първо, в този формат се създават не само конфигурационни файлове, но и файлове с външни отчети и обработка. В интернет срещнах името Compound-file. Може би е добре установен сред старите 1C, но не ми харесва много.
Гледаме вътре
Логическата единица за съхранение на данни в рамките наконтейнера едокументът. Документът е смислен пълен набор от данни, които могат да бъдат прочетени и интерпретирани по някакъв начин. Специално не използвам термина “файл ”, защото ще запазя това име за друг обект, за който малко по-късно.
И така, най-общо казано, CF (EPF/ERF) файлът еконтейнер, който съхранявадокументи.

Всеки документ в контейнера може да бъде разделен наблокове. Минималната физическа единица за съхранение на данни еблок, но смислена логическа единица едокумент. С други думи, документите вътре в контейнера могат да лежат под формата на отделни части (блокове ) и за да се прочете съдържанието на документа, всички негови части трябва да бъдат събрани и комбинирани.

Контейнерна структура
Контейнерът включва следните части (по ред):
- Заглавка на контейнера
- Адресът на първия празен блок, където могат да се добавят данни
- Размер на блока по подразбиране
- Брой файлове в контейнер
За да прочетете съдържанието на контейнер, трябва да прочетете документа със съдържанието. Въпреки това, тъй катодокументът се състои отблокове, първо трябва да научите как да сглобявате пълен документ от същите тези блокове.
Блокова структура
Вътре в контейнера, тук и там, има магическа константа, обозначаваща определена "празнота" - това е числото 0x7fffffff.
Константата 0x7fffffff е стойността на INT_MAX, т.е. максималната стойност на 4-байтово цяло число със знак.
Логически "файлове"
Споменах, че ще запазя термина "файл " за по-късно. Тези времена са тук :)
Цялата конфигурация се съхранява в контейнера катофайлове. Ако си спомним училищния курс по компютърни науки, тогава ще си спомним, че „файлът“, както ни казаха, е именувандокумент.
Файлът се различава от "документа" по това, че има име и може да бъде посочен с това име. Ако анализираме съдържанието на конфигурацията и изградим дърво с метаданни, тогаванамираме във файловете много препратки към други файлове. Процедурата за четене на конфигурацията работи с имената нафайловете и ги препраща по име.
За да обобщим, можем да кажем следното: в контейнера има различнидокументи, но някои от тях имат име. Такива документи се наричат "файлове " и те не са официални, а директно прилагани.Файловете съхраняват информацията за метаданни за конфигурацията.
Файлови компоненти
Всеки файл се състои от двадокумента :
- Документ с атрибути, който съдържа името на файла и датите на създаване/модифициране
- Документът със съдържанието, който съдържа действителното тяло на файла
съдържанието на контейнера
Сега, след като всички компоненти са изразени, остава да разгледаме може би най-важния контейнерен документ - документът със съдържанието, който показва местоположението на всички контейнерни файлове. Както бе споменато по-горе, документът със съдържанието е първият документ на контейнера и идва веднага след заглавката на контейнера.
Съдържанието е масив от записи, всеки от които сочи къмфайл. Тъй като файлът се състои от два документа (атрибути и съдържание), входът на съдържанието сочи към двата. Записът на съдържанието е три INT32 числа:
- Адресът (изместване във файла) на атрибутния документ
- Адрес (изместване във файл) на документа със съдържание
- Номер 0x7fffffff (маркер за край на записа).

Напомням ви, че всеки документ може да бъде разделен на блокове (фрагментиран). Алгоритъмът за сглобяване на документ от блокове ще бъде разгледан по-долу.
Характеристики на компресиране на данни.
Един контейнер може да съдържа голямо разнообразие от файлове. По правило това са текстови файлове, кодирани в UTF-8. Въпреки това средконтейнерните файлове могат да съдържат други контейнерни файлове. Най-лесният начин да се направи аналогия с файловата система. Контейнерът е директория, а файловете вътре в контейнера са нейното съдържание. Една директория може да съдържа други директории.
Основната директория на тази "файлова система" е самият *.CF файл. В него може да има други контейнерни файлове, всъщност - вложени директории, които се четат точно по същия алгоритъм и имат абсолютно същата структура.
Има обаче една особеност на основната директория. Всички файлове сдокументи със съдържание в главната директория се компресират с помощта на алгоритъма Deflate. Съдържанието на файлове във вложени директории вече не се компресира. Просто казано, на най-високото ниво на контейнерния файл телата на всички файлове са компресирани, но ако файлът вътре в контейнера сам по себе си е контейнер, тогава файловете вътре в него вече ще бъдат записани в чистата си форма (без компресия).
Верига от безплатни блокове
Кратко резюме на теоретичната част
Да опипаме вече байтовете
И така, време е да разгледаме как са конкретно подредени всички споменати по-горе образувания.
Основният начин за четене на данни от контейнер е да се прочете веригата от блокове, които съставят определени документи. Изглежда, че би било правилно да се започне с принципа на четене на блокови документи.
Четене на документ на блокове
Всеки документ в контейнер трябва да започва със заглавка на блок. В този случай документът може да бъде разделен на няколко блока. За да прочетете документ, е необходимо да го "съберете" от блокове.
И така, заглавката на блока е 31-байтов низ. Този ред изглежда така:
[CRLF][Размер на целия документ][Интервал][Текущ размер на блок][Интервал][Адрес на следващ блок] [Интервал] [CRLF], където:
Веднага след заглавката на блокаидва тялото на блока, което е с дължината, зададена в полето "Размер на текущия блок".

Помислете за фигурата: дължината на целия документ е 0x54 байта, тези 0x54 байта са маркирани в червено. Това са данни от документи. Дължината на блока е 0x200 байта, т.е. по-голяма от дължината на самия документ. Поради тази причина останалите блокови данни са "нули" неизползвано пространство. Значимите байтове са тези, маркирани с червена рамка.
Четенето трябва да продължи, докато се срещне стойността 0x7fffffff в полето "Адрес на следващия блок" или докато не се прочете броят байтове, посочен в полето "Размер на целия документ".
Полето "Размер на целия документ" има значение само за първия блок. Във всички следващи блокове на документа той има стойност 0x00000000.
Формат на заглавката на контейнера
Заглавката на контейнера е с дължина 16 байта и се състои от следните полета: