Главная
Трудоустройство
Ваши объявления
Наши новости
Информация







СОМ-хранилища: подпольная файловая система

Рано или поздно перед многими программистами встает вопрос - в каком формате хранить данные своей программы? Хорошо, если сохраняемая информация - это записи с фиксированной длиной. А если нужно записать разнородные данные - да еще в одном файле (чтоб потом не разбираться с десятком-другим файлов)?









Тут на помощь приходит сама Windows с технологией структурированного хранилища данных.

Определения

Структурированные хранилища данных - это файлы особой "самодокументированной" структуры, в которых могут мирно уживаться разнородные данные (от простого текста до фильмов, архивов и… программ). Поскольку эта технология является неотъемлемой частью Windows, доступ к ней возможен из любого поддерживающего технологию COM средства программирования. Одним из таких инструментов является Delphi, на основе которого будет описана технология доступа к структурированным хранилищам данных.

COM-хранилища напоминают иерархическую файловую систему. Так, в них есть корневое хранилище (Root Entry), в котором могут содержаться как отдельные потоки ("файлы"), так и хранилища второго уровня ("каталоги"). В них, в свою очередь,- хранилища третьего уровня и т.д. Управление каждым хранилищем и потоком осуществляется посредством отдельного экземпляра интерфейса: IStorage - для хранилищ и IStream - для потоков. Рассмотрим конкретнее некоторые операции, реализуемые этими интерфейсами.

Создание и открытие хранилищ

Создание хранилищ осуществляется с использованием функции StgCreateDocFile из модуля ActiveX.pas:

function StgCreateDocfile (pwcsName: POleStr; grfMode: Longint;
reserved: Longint; out stgOpen: IStorage): HResult; stdcall;

где:

  • pwcsName - название хранилища (т. е. название файла);
  • grfMode - флаги доступа (комбинация значений STGM_*);
  • reserved - он и в Африке RESERVED;
  • StgOpen - ссылка на интерфейс IStorage нашего главного хранилища.
  • Результат функции как всегда транслируем в исключения Delphi посредством OleCheck.

    Для открытия хранилища используется функция StgOpenStorage:

    function StgOpenStorage (pwcsName: POleStr; stgPriority: IStorage;
    grfMode: Longint; snbExclude: TSNB; reserved: Longint;
    out stgOpen: IStorage): HResult; stdcall;

    параметр stgPriority указывает на ранее открытый экземпляр главного хранилища (почти всегда nil).

    Когда хранилище открыто…

    Рассмотрим более подробно методы интерфейса IStorage.

    Создание потока - IStorage.CreateStream.

    function CreateStream (pwcsName: POleStr; grfMode: Longint; reserved1: Longint;reserved2: Longint; out stm: IStream): HResult; stdcall;

    Открытие потока - IStorage.OpenStream:

    function OpenStream (pwcsName: POleStr; reserved1: Pointer; grfMode: Longint;reserved2: Longint; out stm: IStream): HResult; stdcall;

    параметры:

  • pwcsName - название потока;
  • grfMode - флаги доступа;
  • reserved1, reserved2 - соответственно;
  • stm - указатель на созданный поток.
  • Можем приступать к чтению (записи) данных из (в) потоков посредством интерфейсов IStream. Тут можно заметить до боли знакомые методы работы с потоками: Read, Write, Seek… - а если так, то почему бы не перевести эти методы в более простую и понятную объектную форму? Для этого воспользуемся наработками Borland, собранными в модуле AxCtrls.pas (точнее - классом TOleStream, который интерпретирует вызовы методов интерфейса IStream в соответствующие методы класса Tstream).

    А чтоб не быть голословным - приведу небольшой пример:

    Implementation
    Uses ActiveX,AxCtrls,ComObj;
    procedure TForm1.Button1Click (Sender: TObject);
    var Stg:IStorage;
    Strm:IStream;
    OS:TOleStream;
    S:String;
    begin
    OleCheck (StgCreateDocfile (Testing.stg,STGM_READWRITE
    or STGM_SHARE_EXCLUSIVE,0,Stg));
    OleCheck (Stg.CreateStream (Testing,STGM_READWRITE
    or STGM_SHARE_EXCLUSIVE,0,0,Strm));
    OS:=TOleStream.Create (Strm);
    try
    S:=This is the test;
    OS.WriteBuffer (Pointer (S)^,Length (S));
    finally
    OS.free;
    Strm:=nil;
    Stg:=nil;
    end;
    end;
    end.
    
    

    В этом фрагменте мы создаем новое хранилище с одним потоком, в который записываем строку S. Естественно, ничто не мешает нам написать например:

    Image1.Picture.Bitmap.SaveToStream (OS)
    
    

    - и тем самым записать в поток Testing изображение (вот она - "универсальная мусоросвалка"). Теперь ненадолго отвлечемся от Delphi и посмотрим на наш файл с точки зрения, скажем, Far (или VC)… Посмотрели? Если там же открыть любой документ Word (Excel), убедимся, что структура будет такой же, что и в нашем файле. Проверка принадлежности файла к формату хранилищ проводится с использованием функции StgIsStorageFile из ActiveX.pas:

    function StgIsStorageFile (pwcsName: POleStr): HResult; stdcall;

    Результат:

  • S_OK (0) - файл является хранилищем данных;
  • S_FALSE (1) - файл не является хранилищем.
  • Кроме того, эта функция может принимать значения STG_E_INVALIDFILENAME (если имя задано неправильно) и STG_E_FILENOTFOUND (если файла с таким именем не существует).

    Чтение

    Чтение данных из хранилища производится так же, как и чтение из стандартного потока Delphi. Все, что для этого требуется, это создать объект TOleStream с использованием возвращаемого функцией IStorage.OpenStorage значения stm:

    procedure TForm1.Button2Click (Sender: TObject);
    var Stg:IStorage;
    Strm:IStream;
    OS:TOleStream;
    S:String;
    begin
    OleCheck (StgOpenStorage (Testing.stg,nil,STGM_READWRITE
    or STGM_SHARE_EXCLUSIVE, nil,0,Stg));
    OleCheck (Stg.OpenStream (Testing,0,STGM_READWRITE
    or STGM_SHARE_EXCLUSIVE,0,Strm));
    OS:=TOleStream.Create (Strm);
    try
    SetLength (S,OS.Size);
    OS.ReadBuffer (Pointer (S)^,OS.Size);
    Edit1.Text:=S;
    finally
    OS.free;
    Strm:=nil;
    Stg:=nil;
    end;
    end;
    
    

    После выполнения этого кода мы увидим в Edit1 ранее записанное нами: "This is the test".

    Исследование хранилищ

    Хорошо… мы создали хранилище, записали в него данные и прочитали их. Но мы сделали это, ЗНАЯ имя потока, в котором записаны наши данные. Но как быть, если мы не знаем структуры хранилища? Для этого в интерфейсе IStorage предусмотрен механизм перечисления элементов хранилища - он содержится в интерфейсе IEnumStatStg (указатель на который возвращается функцией IStorage.EnumElements):

    function EnumElements (reserved1: Longint; reserved2: Pointer; reserved3: Longint;out enm: IEnumStatStg): HResult; stdcall;

    Употребление этой функции происходит так:

    OleCheck (Stg.EnumElements (0,nil,0,Enum));
    
    

    После этого используем только методы интерфейса IenumStatStg (Next, Skip, Reset, Close). Самым важным из этих методов на данный момент является для нас метод Next:

    Next (celt:Longint; out elt; pceltFetched: PLongint): HResult; stdcall;

    Он может принимать следующие параметры:

  • Celt - количество элементов структуры, которое будет извлечено при его вызове;
  • Elt - массив-приемник элементов типа TstatStg;
  • PceltFetched - указатель на переменную, в которую будет записано действительное количество извлеченных элементов.
  • Для примера воспользуемся любым doc-файлом и перечислим его элементы:

    procedure TForm1.Button2Click (Sender: TObject);
    var Stg:IStorage;
    Enum:IEnumStatStg;
    Data:TStatStg;
    begin
    OleCheck (StgOpenStorage (D:.doc,nil,STGM_READWRITE
    or STGM_SHARE_EXCLUSIVE,nil,0,Stg));
    OleCheck (Stg.EnumElements (0,nil,0,Enum));
    try
    While Enum.Next (1,Data,nil)=S_Ok do
    ListBox1.Items.Add (Format (%s
    (%d),[Data.pwcsName,Data.cbSize]));
    finally
    Stg:=nil;
    Enum:=nil;
    end;
    end;
    
    

    Структура TStatStg содержит, помимо pwcsName и cbSize, следующие поля:

    pwcsName: POleStr; название потока или хранилища
    dwType: Longint; тип элемента (флаги типа STGTY_*)
    cbSize: Largeint; размер конкретного элемента
    mtime,ctime,atime: TFileTime; дата модификации, создания, последнего доступа
    grfMode: Longint; флаг доступа
    grfLocksSupported: Longint; не используется в хранилищах
    clsid: TCLSID; идентификатор класса хранилища
    grfStateBits: Longint; статусные биты
    reserved: Longint; зарезервирован

    Описанные интерфейсы и методы помогут вам не только использовать уже существующие COM-хранилища (такие как документы MS Office), но и создавать собственные,- благодаря чему ваши данные будут храниться в компактном и согласованном виде.



    Михаил Продан



    www.cybersecurity.ru
    Новинки операционных систем 13-03-2007
    Отображение скрытого оборудования в Диспетчере устройств 26-08-2008 Новинки операционных систем
    «Призрачные» и скрытые устройства, которые не отображаются в Диспетчере устройств Windows (Windows Device Manager), могут приводить к сбоям и системным конфликтам. В этой статье мы расскажем о том, как заставить Диспетчер показывать все скрытые устройства для облегчения диагностики возникающих проблем.Один из самых странных недостатков XP, связанных с оборудованием, – это наличие «призрачных» и скрытых устройств, которые не отображаются в Диспетч...


    35% покупателей компьютеров с Windows Vista переходят на Windows XP - исследование 22-08-2008 Новинки операционных систем
    Западные исследователи из компании Devil Mountain Software провели занятное исследование, по итогам которого выяснилось, что более трети покупателей новых компьютеров и ноутбуков в США берут машины с предустановленными ОС Windows Vista, однако сразу после покупки делают откат ОС до версии Windows XP.Исследователи отмечают, что из более чем 3 000 опрошенных покупателей новых ПК или ноутбуков, 35% сообщили, что сразу же после покупки или непоср...


    Новая жизнь Windows XP 28-07-2008 Новинки операционных систем
    Очередной сюрприз преподносит нас корпорация Microsoft: в рамках договора о сотрудничестве ее и некоммерческого фонда One Laptop Per Child (OLPC, что переводится дословно как «по ноутбуку каждому ребенку») было достигнуто соглашение о том, что софтверный гигант подготовит к выпуску специализированную версию WindowsXP, которая будет оптимально работать на особых ноутбуках XO, созданных в рамках такой программы («стодолларовые» ноутбуки, как Вы мог...

    Copyright © 2005
    "service-centers.com.ua"


    Rambler's Top100   Рейтинг@Mail.ru

    Работа
    Карта сайта
    О сайте
    Реклама
    все объявления
    поиск резюме
    поиск вакансий
    добавить резюме
    добавить вакансию

    Все объявления
    Компьютеры, оргтехника
    Автомобили
    Продукты питания
    Аудио, Фото, Видео
    Связь
    Отдых, путешествия
    Мебель
    Разное
    Добавить объявление
     Автомобили
     Ремонтно-строительные услуги
     Пресс-релизы
     Железо
     Soft
     Мобильная планета
     Для милых дам
     Родительский клуб
     Недвижимость
     Домашний очаг, усадьба
     Строительство
     Обустройство и безопасность дома
     Сантехника