Каталог статей
Главная » Статьи » S3DecoderLib |
S3DecoderLib: Sims3Pack. Реализация декодера
|
Формат Sims3Pack и его декодирование: Часть практическая, реализация декодера [ Стабильный билд • Описание формата • Типы данных ]
Програмный модуль и версия S3PackDecoder.pas, rev.120825
Типы данных
class TS3PackDecoder – реализация декодера Декодер представляет собой наследника класса TComponent и может (и должен во избежание багов с парсером xml) устанавливаться на форму. Для работы с исходным файлом используется первичный поток, в его качестве допустим любой (естественно неабстрактный) потомок TStream; он должен быть создан и файл загружен в него – сделано это для того чтобы не привязываться к размещению исходного файла. Для освобождения первичного потока нельзя использовать его "родные" методы, для этого используется метод FreeStream декодера.type TS3PackDecoder = class(TComponent) private FCount: integer; // число записей в индекной таблице FHeader: TS3PackHeader; // заголовок файла FItems: TS3PackItems; // параметры файлов в архиве FStream: TStream; // поток чтения FXMLDecoder: TXMLDocument; // парсер xml FPackageName: string; // имя пакета FPackageDescription: string; // описание пакета protected function Alloc: TS3PackItem; // добавляет запись в индексную таблицу и возвращает ее public constructor Create(AOwner: TComponent); override; // конcтруктор класса destructor Destroy; override; // деструктор класса procedure FreeStream; // освобождает вторичные потоки, освобождает первичный поток procedure Decode(AReader: TStream); // связывает поток декодирования, декодирует индексную таблицу property Items: TS3PackItems read FItems; // декодированная индексная таблица property Count: integer read FCount; // число записей в индекной таблице property Header: TS3PackHeader read FHeader; // заголовок файла property PackageName: string read FPackageName; // имя пакета property PackageDescription: string read FPackageDescription; // описание пакета end; // TS3PackDecoder class Свойства Items: TS3PackItems – массив записей по каждому из файлов в пакете, только чтение; Count: integer – число файлов в пакете, только чтение; Header: TS3PackHeader – заголовок пакета, содержит те самые 17 байт, категорически не рекомендуется лезть в него грязными руками (чистыми, кстати, тоже) – свойство информационное для отладки, только чтение; PackageName: string, имя пакета, если есть русская локализация, то берется из LocalizedNames\ru-RU, иначе какая есть (обычно английская) из DisplayName манифеста, только чтение; PackageDescription: string, описание пакета, если есть русская локализация, то берется из LocalizedDescriptions\ru-RU, иначе какая есть (обычно английская) из Description манифеста, только чтение;
Методы constructor Create(AOwner: TComponent) – конструктор класса; destructor Destroy – виртуальный деструктор, освобождает все связанные потоки (и первичный и вторичные) – естественно вместо него лучше использовать метод Free; procedure FreeStream – освобождает вторичные потоки, освобождает первичный поток, после его вызова нельзя использовать остальные поля и методы для данного файла, для освобождения потока нельзя использовать его "родные" методы; procedure Decode(AReader: TStream) – связывает поток декодирования с декодером, декодирует индексную таблицу, должен вызывается первым, все остальные поля и методы используются после нее, до ее вызова состояние полей неопределенно, кроме Count, который равен 0; function Alloc: TS3PackItem – защищенный метод, увеличивает индексную запись на один элемент и вызывает его конструктор;
Пример использования Практическое использование может быть, например, такое:procedure TfrmMain.btnSims3PackClick(Sender: TObject); var i: integer; begin if not dlgOpenS3Pack.Execute then exit; lstLog.Clear; S3PackDecoder.Decode( TFileStream.Create(dlgOpenS3Pack.FileName, fmOpenRead)); // (1) AddDebug('file=%s', [dlgOpenS3Pack.FileName]); // (2) AddDebug('name=%s', [S3PackDecoder.PackageName]); AddDebug('description=%s', [S3PackDecoder.PackageDescription]); AddDebug('-------------------', []); barProgress.Max:= S3PackDecoder.Count-1; Application.ProcessMessages; for i:= 0 to S3PackDecoder.Count-1 do with S3PackDecoder.Items do begin // (3) AddDebug('name=%s', [FileName]); // (4) AddDebug(' offset=%.6Xh, size=%.6Xh, type=%s', [Offset, Length, ContentType]); Decode(TMemoryStream.Create); // (5) Stream.SaveToFile('unpack\'+FileName); FreeStream; barProgress.Position:= i; Application.ProcessMessages; end; S3PackDecoder.FreeStream; // (6) end;
В примере, выбранный пользователем файл: 1) открывается и декодируется; 2) в лог добавляются данные манифеста; 3) затем для каждой записи: 4) - в лог добавляются данные о ней; 5) - она декодируется и сохраняется на диск; 6) первичный поток закрывается; Пример довольно условный, т.к. для записи на диск TFileStream подходит лучше – зато иллюстрирует правильное создание, доступ и уничтожение вторичных потоков. Обратите внимание на необходимость использования вызова Application.ProcessMessages в теле цикла декодирования, в случае его отсутствия при больших файлах заметна "заморозка" программы. | |
Категория: S3DecoderLib | Добавил: crazylab (27.09.2013) | |
Просмотров: 725 |