Slinger писал(а):Борис, спасибо за утилиту. Сейчас более менее внятно потестил:
1) Взял исходник, решил, что в id 441 объект. Пробил это в .dat, получил рабочую таблицу, после чего упаковал, исключив все ошибки.
2) Взял исходник, прогнал через recovery, получил 492 объекта. Упаковал таблицу, дабы не морочаться со стилями, которые и так были, но не отображались, потому что опять-таки соответствующие байты были побиты.
3) Обнаружил, что в восстановленной recovery таблице есть дубликаты объекты. Вычистил их, и объектов стало 472. Так же удалил дублирующий объект из моей таблицы. Соответственно объектов стало 440.
Итого - на 32 реально "работающих" объектов больше. Примечательно, что все они в колонке rec_status имеют префикс D. Что это кстати значит, Борис ?
И как программа переопределяет заново файл .id ? С помощью библиотеки Mitab ?
Я точно это не описал в README.TXT ? Если нет, то я поправлю как доберусь до программы, хотелось по быстрее выложить.
Буква D - означает, что запись была отмечена как удаленная. В DAT (DBF - атрибутика) - это единственное знание, кроме RowID. Для MAP есть следующие значения в 4-х символьном поле:
1-ы символ:
" " - запись не была отмечена удаленной; D - запись была отмечена удаленной.
2-ой - E - запись прочиталась с ошибкой (результат не предсказуем); U - неизвестный тип, запись прочитана нормально, но т.к. не известен размер заголовка этого типа, все записи до конца блока пропущены и не восстановлены.
3-й и 4-й - это внутренний номер типа геоданных. 2-х байтовое целое. Отличается от номера, который возвращает ObjectInfo()/
---
Нет я не использую никакой библиотеки, т.к. я не понял, что она делает. Я в свое время пытался в ней разобраться, но там очень путанные ссылки на абстрактные объекты и т.д. Поэтому я просто взял двоичные описания форматов, какие нашел в сети и воссоздал файлы по ним.
DAT = DBF III - только все данные хранятся в полях строк (ХЗ знаю почему). Но какие бы данные не были записаны в поле, оно помечено в DBF Как символьное. Тут проблем нет - формат много кратно описан, добавить в него строки или поля не представляет труда, равно как и исправить значения. В таблице, с которой начался разбор, файл DAT - битый, по какой то причине он укорочен в 49 или 56 (я уже не помню) записей. Из-за этого все, что далее не распознается MI, как объекты, хотя графическая часть MI - их отображает на экране.
MAP - описан скудно, но основные принципы и структуру, описали к 2007 году, правда в описании не оказалось типа 26, который и давал ошибку в программе версии 2011 года. Формат логичный, но многодельный, в нем даже есть внутренний индекс, который призван ускорить выборку, но этот раздел никто не описал. Хотя видимо он не является проблемой, т.к. FME Universal Translator (или его мини версия UT из утилит Mapinfo) прекрасно умеют создавать такой индекс. Кстати часть знаний была почерпнута из каких-то разделов документации по FME, вернее намеков в ней. Файл блочной структуры. Каждый блок имеет размер &H200 - волшебное число, блоки имеют несколько видов. Для программы главный - блок описания гео-объектов. В нем хранится номер RowID и ссылка на блок с геометрией объекта. Поле RowID - это просто порядковый номер записи в файле DAT, если он больше 0, если меньше - это то же RowID, но умноженный на -1. Исправив это номер получаем восстановленную запись с геометрией. Синхронно надо изменить запись в DAT, где удаление кодируется знаком "*" с начале записи. Так MAP ссылается на DAT - при каждом гео-объекте есть прямая ссылка на строчку с атрибутикой. Обратное неверно, т.к. был использован чужой формат DBF (спасибо, т.к. он описан на 200%), но в DBF не было предусмотрено место для ссылок, т.е. тип такой отсутствовал. Хотя это странно, т.к. по факту везде для ссылок использовано смещение записи от начала файла в виде длинного целого о 4-х байтах, можно было с тем же успехом внести ссылку в поля DBF. Но сделали по другому, видимо для скорости:
Создали файл
ID он компактный, и видимо в эпоху ограниченной оперативной памяти, это было критично. Файл ID - это простой список ссылок на описание гео-объекта в файле MAP. 4-байта = смещение описания от начала файла MAP.
Все... Ничего больше. Просто последовательный список ссылок. 4 байта на число без разделителей. Как идут записи в DAT файле, ровно в таком порядке идут и ссылки. Это и позволило вам восстановить файл, просто добавив отсутствующие строки в файл DAT. Видимо, ID содержит ссылки только на неудаленные записи, иначе простое добавление в DAT не дало бы эффекта.
Спасибо создателям формата! Без смеха. Они заложили такую избыточность, что она позволяет воссоздать данные, просто перебирая их в двоичном виде.
Работа программы проста: она читает файл MAP и вычленяет из него блоки описания гео-объектов. Потом перебирает заголовки гео-объектов в этом блоке. Для каждого заголовка обязательно хранится тип и RowId. Дальше идут нюансы конкретного типа гео-объекта. Например, для точки вся информация хранится в заголовке, а для полилинии хранится ссылка на блок описания координат и количество точек в полилинии, если в ней 1 сегмент. За полилинии из 2 и более сегментов отвечает другой тип гео-объектов. Неизвестный тип = неизвестный размер записи, неизвестно где начинается описание СЛЕДУЮЩЕГО объекта, до конца блока вся информация не может быть прочитана. НО этот объект - прочитан и восстановлен! Вернемся к работе: сканируем информацию о гео-объектах. При каждом из них известный RowId (или номер записи, включая отмеченные как удаленные, от начала файла DAT) - вот по этому RowId и создаем запись в новый DAT, со служебной информацией - новый порядковый номер (RowID_new), старый RowId - Который был записан в MAP, его при обработке мы меняем на новый RowID (опять же просто номер по порядку, но уже в переборе MAP), смещение, и статус в исходном файле - удаленный да/нет и т.п. (см. выше).
Параллельно пишем к создаваемому DAT новый ID - адреса геообъектов. Поскольку геообъектов с удаленными может быть больше, чем в исходном файле, ID обычно больше исходного, но в случае когда пришлось пропустить объекты после неизвестного типа, их может быть и меньше. В этом случае спасти битые гео-объекты объекты можно именно так как удалось "руками" - надо добавить к DAT файлу недостающее количество записей и взять старый ID. Естественно, если и он не испорчен.
Восстановить случайно удаленные объекты, а это и было изначальной целью программы Recovery, таким образом не удасться. В случае Recovery - спасение геометрии - это просто бонус, происходящий из структуры файлов.