为什么IStream :: Commit无法将数据写入文件?

时间:2015-11-09 03:59:07

标签: c++ windows winapi com

我有一个二进制文件,当我打开它时,我使用::StgOpenStorage STGM_READWRITE | STGM_SHARE_DENY_WRITE | STGM_TRANSACTED模式来获取名为rootStorage的根存储。然后,我使用rootStorage.OpenStream STGM_READWRITE | STGM_SHARE_EXCLUSIVE模式获取名为subStream的子流。

接下来,我用subStream.Wirte(...)写了一些数据,并调用了subStream.Commit(STGC_DEFAULT),但是它无法在文件中写入数据。

我也试过了rootStorage.Commit(STGC_DEFAULT),可以写出数据。 但是当我使用UltraCompare Professional - Binary Compare将原始文件与我打开的文件进行比较时,在文件的末尾写了很多额外的数据。额外的数据似乎是从文件的开头。

我只想在打开文件时将一些数据写入文件。我该怎么办?

2 个答案:

答案 0 :(得分:0)

二进制文件比较可能不适用于结构化存储文件。问题是结构化存储文件通常在其中分配了额外的空间 - 处理事务处理模式和扩展文件。如果要进行文件比较,则需要更多工作。您必须在每个文件中打开根存储,然后打开流,并对流进行二进制比较。

答案 1 :(得分:0)

我发现为什么我的文件中有额外的数据。

<强> 1 即可。我为什么要使用IStorage.Commit()

我使用STGM_READWRITE模式创建存储空间。它被称为交易模式。在事务处理模式下,更改会累积,并且在完成显式提交操作之前不会反映在存储对象中。所以我需要致电rootStorage.Commit()

<强> 2 即可。为什么在调用IStorage.Commit(STGC_DEFAULT)

后会有额外的数据

根据website

OLE提供的复合文件使用两阶段提交过程,除非STGC_OVERWRITE参数中指定了grfCommitFlags。这个两阶段过程确保了在提交操作失败的情况下数据的健壮性。首先,所有新数据都写入底层文件中的未使用空间。如有必要,将为文件分配新空间。成功完成此步骤后,将使用单个扇区写入更新文件中的表,以指示将使用新数据代替旧数据。旧数据成为下一次提交时使用的可用空间。因此,旧数据可用,并且可以在提交更改时发生错误时进行恢复。如果指定了STGC_OVERWRITE,则使用单阶段提交操作。