STGM 常量

STGM 常量是指示创建和删除对象的条件以及对象的访问模式的标志。 STGM 常量包含在 IStorageIStreamIPropertySetStorage 接口以及 StgCreateDocfileStgCreateStorageExStgCreateDocfileOnILockBytesStgOpenStorageStgOpenStorageEx 函数中。

这些元素通常使用 OR运算符进行组合。 它们按组进行解释,如下表所示。 使用单个组中的多个元素无效。

创建对象时,请使用创建组中的标志,例如使用 StgCreateStorageExIStorage::CreateStream

有关事务的详细信息,请参阅“备注”部分。

Group 标志
Access STGM_READ 0x00000000L
STGM_WRITE 0x00000001L
STGM_READWRITE 0x00000002L
共享 STGM_SHARE_DENY_NONE 0x00000040L
STGM_SHARE_DENY_READ 0x00000030L
STGM_SHARE_DENY_WRITE 0x00000020L
STGM_SHARE_EXCLUSIVE 0x00000010L
STGM_PRIORITY 0x00040000L
创建 STGM_CREATE 0x00001000L
STGM_CONVERT 0x00020000L
STGM_FAILIFTHERE 0x00000000L
事务处理 STGM_DIRECT 0x00000000L
STGM_TRANSACTED 0x00010000L
事务处理性能 STGM_NOSCRATCH 0x00100000L
STGM_NOSNAPSHOT 0x00200000L
直接 SWMR 和简单 STGM_SIMPLE 0x08000000L
STGM_DIRECT_SWMR 0x00400000L
发布时删除 STGM_DELETEONRELEASE 0x04000000L

STGM_READ

0x00000000L

指示对象为只读,这意味着无法进行修改。 例如,如果使用 STGM_READ 打开流对象,可以调用 ISequentialStream::Read 方法,但 ISequentialStream::Write 方法可能不调用。 同样,如果使用 STGM_READ 打开存储对象,可以调用 IStorage::OpenStreamIStorage::OpenStorage 方法,但 IStorage::CreateStreamIStorage::CreateStorage 方法可能不调用。

STGM_WRITE

0x00000001L

允许您保存对对象的更改,但不允许访问其数据。 提供的 IPropertyStorageIPropertySetStorage 接口的实现不支持此只写模式。

STGM_READWRITE

0x00000002L

启用对对象数据的访问和修改。 例如,如果在此模式下创建或打开流对象,可以同时调用 IStream::ReadIStream::Write。 请注意,此常量不是STGM_WRITESTGM_READ元素的简单二进制 OR 运算。

STGM_SHARE_DENY_NONE

0x00000040L

指定不拒绝对象的后续打开读取或写入访问。 如果未指定共享组中的标志,则假定此标志。

STGM_SHARE_DENY_READ

0x00000030L

阻止其他人随后在 STGM_READ 模式下打开对象。 它通常用于根存储对象。

STGM_SHARE_DENY_WRITE

0x00000020L

防止其他人随后打开对象进行 STGM_WRITESTGM_READWRITE 访问。 在事务处理模式下,共享 STGM_SHARE_DENY_WRITESTGM_SHARE_EXCLUSIVE 可以显著提高性能,因为它们不需要快照。 有关事务的详细信息,请参阅“备注”部分。

STGM_SHARE_EXCLUSIVE

0x00000010L

防止其他人随后以任何模式打开对象。 请注意,此值不是STGM_SHARE_DENY_READSTGM_SHARE_DENY_WRITE值的简单按位 OR 运算。 在事务处理模式下,共享 STGM_SHARE_DENY_WRITESTGM_SHARE_EXCLUSIVE 可以显著提高性能,因为它们不需要快照。 有关事务的详细信息,请参阅“备注”部分。

STGM_PRIORITY

0x00040000L

打开具有对最近提交的版本的独占访问权限的存储对象。 因此,在优先级模式下打开对象时,其他用户无法提交对对象的更改。 你可以获得复制操作的性能优势,但会阻止其他人提交更改。 限制对象在优先级模式下打开的时间。 必须使用优先级模式指定 STGM_DIRECTSTGM_READ ,并且不能指定 STGM_DELETEONRELEASESTGM_DELETEONRELEASE 仅在创建根对象时有效,例如使用 StgCreateStorageEx。 打开现有根对象(例如 使用 StgOpenStorageEx)时,它无效。 创建或打开子元素(例如 使用 IStorage::OpenStorage)时,它也无效。

STGM_CREATE

0x00001000L

指示应在新对象替换现有存储对象或流之前删除它。 仅当成功删除现有对象时才指定此标志时,才会创建新对象。

尝试创建以下标志时使用此标志:

  • 磁盘上的存储对象,但存在该名称的文件。
  • 存储对象内的 对象,但存在具有指定名称的对象。
  • 一个字节数组对象,但存在具有指定名称的字节数组对象。

此标志不能用于打开操作,例如 StgOpenStorageExIStorage::OpenStream

STGM_CONVERT

0x00020000L

创建新对象,同时保留名为“Contents”的流中的现有数据。 对于存储对象或字节数组,无论现有文件或字节数组当前是否包含分层存储对象,旧数据都会格式化为流。 此标志只能在创建根存储对象时使用。 它不能在存储对象中使用;例如,在 IStorage::CreateStream 中。 同时使用此标志和 STGM_DELETEONRELEASE 标志也无效。

STGM_FAILIFTHERE

0x00000000L

如果存在具有指定名称的现有对象,则会导致创建操作失败。 在这种情况下,返回 STG_E_FILEALREADYEXISTS 。 这是默认创建模式;也就是说,如果未指定其他创建标志,则隐式 STGM_FAILIFTHERE

STGM_DIRECT

0x00000000L

指示在直接模式下,每次对存储或流元素的更改都会在发生时写入。 如果既未指定 STGM_DIRECT ,也未指定 STGM_TRANSACTED ,则这是默认值。

STGM_TRANSACTED

0x00010000L

指示在事务处理模式下,仅当调用显式提交操作时,才会缓冲和写入更改。 若要忽略这些更改,请在 IStreamIStorageIPropertyStorage 接口中调用 Revert 方法。 IStorage 的 COM 复合文件实现不支持事务处理流,这意味着只能在直接模式下打开流,并且不能还原更改它们,但支持事务处理存储。 IPropertySetStorage 的复合文件、独立和 NTFS 文件系统实现同样不支持事务处理简单属性集,因为这些属性集存储在流中。 但是,支持非简单属性集的事务处理,可以通过在 IPropertySetStorage::CreategrfFlags 参数中指定 PROPSETFLAG_NONSIMPLE 标志来创建。

STGM_NOSCRATCH

0x00100000L

指示在事务处理模式下,通常使用临时暂存文件来保存修改,直到调用 Commit 方法。 指定 STGM_NOSCRATCH 允许将原始文件的未使用部分用作工作区,而不是为此创建新文件。 这不会影响原始文件中的数据,在某些情况下可以提高性能。 如果不同时指定 STGM_TRANSACTED,则指定此标志无效,并且此标志只能在根打开的情况下使用。 有关 NoScratch 模式的详细信息,请参阅备注部分。

STGM_NOSNAPSHOT

0x00200000L

当使用 STGM_TRANSACTED 且不使用 STGM_SHARE_EXCLUSIVESTGM_SHARE_DENY_WRITE 打开存储对象时 使用此标志。 在这种情况下,指定STGM_NOSNAPSHOT可防止系统提供的实现创建文件快照副本。 相反,对文件的更改将写入文件的末尾。 除非在提交期间执行合并,并且文件上只有一个当前编写器,否则不会回收未使用的空间。 在没有快照模式下打开文件时,如果不指定STGM_NOSNAPSHOT,则无法执行另一个打开操作。 此标志只能在根打开操作中使用。 有关 NoSnapshot 模式的详细信息,请参阅备注部分。

STGM_SIMPLE

0x08000000L

在有限但经常使用的情况下,提供复合文件的更快实现。 有关详细信息,请参见“备注”部分。

STGM_DIRECT_SWMR

0x00400000L

支持单编写器、多读取程序文件操作的直接模式。 有关详细信息,请参见“备注”部分。

STGM_DELETEONRELEASE

0x04000000L

指示释放根存储对象时,基础文件将被自动销毁。 此功能最适用于创建临时文件。 此标志只能在创建根对象时使用,例如使用 StgCreateStorageEx。 在打开根对象(例如使用 StgOpenStorageEx)或创建或打开子元素(例如使用 IStorage::CreateStream)时,它无效。 同时使用此标志和STGM_CONVERT标志也无效。

备注

可以组合这些标志,但只能从每个相关标志组中选择一个标志。 通常,必须为使用这些常量的所有函数和方法指定每个访问和共享组中的一个标志。 其他组中的标志是可选的。

事务处理模式

指定 STGM_DIRECT标志时,只能从访问组和共享组指定以下标志组合之一。

    STGM_READ      | STGM_SHARE_DENY_WRITE
    STGM_READWRITE | STGM_SHARE_EXCLUSIVE
    STGM_READ      | STGM_PRIORITY

请注意,直接模式是无 STGM_TRANSACTED所隐含的。 也就是说,如果未指定 STGM_DIRECTSTGM_TRANSACTED ,则假定 STGM_DIRECT

指定 STGM_TRANSACTED 标志后,在事务处理模式下创建或打开对象。 在此模式下,对 对象的更改在提交之前不会保留。 例如,在调用 IStorage::Commit 方法之前,不会保留对事务处理存储对象的更改。 如果在调用 Commit 方法之前 (最终发布) 释放存储对象,或者调用 IStorage::Revert 方法,则对此类存储对象的更改将丢失。

在事务处理模式下创建或打开对象时,实现必须同时保留原始数据和对此数据的更新,以便可以在必要时还原更新。 这通常通过将更改写入暂存区域,直到提交这些更改,或者通过创建一个副本(称为快照)对最近提交的数据执行。

在事务处理模式下打开根存储对象时,可以控制暂存数据和快照副本的位置和行为,以使用STGM_NOSCRATCHSTGM_NOSNAPSHOT标志优化性能。 (从 StgOpenStorageEx 函数获取根存储对象;从 IStorage::OpenStorage 方法获取的存储对象是子存储对象。) 通常,暂存数据和快照存储在临时文件中,独立于存储。

这些标志的效果取决于访问根存储的读取器和/或编写器的数量。

在“单编写器”情况下,将打开事务处理模式存储对象进行写入访问,并且不能有对文件的其他访问权限。 也就是说,使用 STGM_TRANSACTED访问STGM_WRITESTGM_READWRITE以及共享 STGM_SHARE_EXCLUSIVE打开文件。 在这种情况下,对存储对象的更改将写入暂存区域。 提交这些更改后,它们将复制到原始存储。 因此,如果实际上未对存储对象进行更改,则不会进行不必要的数据传输。

在“多编写器”情况下,会打开事务处理存储对象以进行写入访问,但共享方式为允许其他写入器。 也就是说,使用STGM_TRANSACTED、访问STGM_WRITESTGM_READWRITE以及共享STGM_SHARE_DENY_READ来打开存储对象。 如果改为指定 共享STGM_SHARE_DENY_NONE ,则情况为“多编写器、多读取者”。 在这些情况下,将在打开操作期间快照原始数据。 因此,即使实际上没有对存储进行更改和/或实际上没有由另一个编写器同时打开,在打开期间仍需要数据传输。 因此,通过在 STGM_SHARE_DENY_WRITESTGM_SHARE_EXCLUSIVE 模式下打开存储对象,可以获得最佳的打开时间性能。 有关存在多个编写器时如何提交更改的详细信息,请参阅 IStorage::Commit

在“单编写器、多读取器”的情况下,将打开事务处理存储对象以进行写入访问,但与读取器共享。 也就是说,编写器使用STGM_TRANSACTED、访问STGM_READWRITESTGM_WRITE以及共享STGM_SHARE_DENY_WRITE来打开存储对象。 存储由具有 STGM_TRANSACTED访问STGM_READ和共享 STGM_SHARE_DENY_NONE的读者打开。 在这种情况下,编写器使用暂存区域来存储未提交的更改。 与上述情况一样,在创建数据快照副本时,读取器会产生开放时间性能损失。

通常,暂存区域是一个临时文件,独立于原始数据。 将更改提交到原始文件时,必须从临时文件传输数据。 为了避免这种数据传输,可以指定 STGM_NOSCRATCH标志。 指定此标志后,存储对象文件的各个部分将用于暂存区域,而不是单独的临时文件。 因此,可以快速提交更改,因为几乎不需要数据传输。 缺点是存储文件可能会变得比本来要大,因为它必须增长到足以容纳原始数据和暂存区域的大小。 若要合并数据并删除此不必要的区域,请在事务处理模式下重新打开根存储,但不设置 STGM_NOSCRATCH 标志。 然后,使用设置STGC_CONSOLIDATE标志调用 IStorage::Commit

与暂存区域一样,快照区域通常也是临时文件,这也可能受到 STGM 标志的影响。 通过指定STGM_NOSNAPSHOT标志,不会创建单独的临时快照文件。 相反,即使每个对象有一个或多个编写器,也不会修改原始数据。 提交更改后,它们将添加到文件中,但原始数据保持不变。 此模式提高效率,因为它无需在打开操作期间创建快照,从而减少了运行时间。 但是,使用此模式可能会导致存储文件非常大,因为文件中的数据永远无法覆盖。 对于在 NoSnapshot 模式下打开的文件大小没有限制。

直接单编写器,Multiple-Reader模式

如前所述,如果在事务处理模式下打开存储对象,则有可能具有存储对象的单个编写器和多个读取器。 还可以通过指定 STGM_DIRECT_SWMR 标志,在直接模式下实现单编写器、多读取器案例。

STGM_DIRECT_SWMR 模式下,一个调用方可以打开对象进行读/写访问,而其他调用方同时打开文件进行只读访问。 将此标志与 STGM_TRANSACTED 标志结合使用是无效 。 在此模式下,编写器使用以下标志打开 对象:

| STGM_DIRECT_SWMRSTGM_READWRITE | STGM_SHARE_DENYWRITE

每个读取器都使用以下标志打开 对象:

| STGM_DIRECT_SWMRSTGM_READ | STGM_SHARE_DENY_NONE

在此模式下,若要修改存储对象,编写器必须获取对该对象的独占访问权限。 当所有读取器都已关闭它时,这是可能的。 编写器使用 IDirectWriterLock 接口获取此独占访问权限。

简单模式

简单模式 (STGM_SIMPLE) 对于执行完整保存操作的应用程序很有用。 它很有效,但具有以下约束:

  • 不支持子存储。
  • 无法封送存储对象以及从中获取的流对象。
  • 每个流都有最小大小。 如果在释放流时写入流中的字节少于最小字节数,则流将扩展到最小大小。 例如,特定 IStream 实现的最小大小为 4 KB。 创建流并写入 1 KB。 在该 IStream 的最终版本中,流大小将自动扩展到 4 KB。 随后,打开流并调用 IStream::Stat 方法将显示大小为 4 KB。
  • 实现并非支持 IStorageIStream 的所有方法。 有关详细信息,请参阅 IStorage - 复合文件实现IStream - 复合文件实现

封送 处理是跨远程过程调用 (RPC) 中的线程或进程边界打包、解压缩和发送接口方法参数的过程。 有关详细信息,请参阅 封送处理详细信息接口封送处理

在简单模式下通过创建操作获取存储对象时:

  • 可以创建流元素,但不能打开。
  • 通过调用 IStorage::CreateStream 创建流元素时,在释放该流对象之前,无法创建另一个流。
  • 写入所有流后,调用 IStorage::Commit 以刷新更改。

在简单模式下通过 Open 操作获取存储对象时:

  • 一次只能打开一个流元素。
  • 无法通过调用 IStream::SetSize 方法或在流末尾之外查找或写入来更改流的大小。 但是,由于所有流都是最小大小,因此,即使最初写入的数据较少,也可以使用该大小达到该大小的流。 若要确定流的大小,请使用 IStream::Stat 方法。

请注意,如果存储元素由不在简单模式下的存储对象修改,则不可能再次在简单模式下打开该存储元素。

要求

要求
最低受支持的客户端
Windows 2000 Professional [仅限桌面应用]
最低受支持的服务器
Windows 2000 Server [仅限桌面应用]
标头
ObjBase.h

另请参阅

ISequentialStream::Read

IStorage

StgCreateDocfile

StgCreateDocfileOnILockBytes

StgCreateStorageEx

StgOpenStorage

StgOpenStorageEx

StgOpenStorageOnILockBytes