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

Why IStream::Commit failed to write data into a file?

本文关键字:数据 文件 IStream Commit 为什么      更新时间:2023-10-16

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

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

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

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

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

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

1。为什么我应该使用IStorage.Commit()

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

2。为什么调用IStorage.Commit(STGC_DEFAULT) 后会有额外的数据

根据本网站:

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