一种编辑大型二进制文件的事务模型

时间:2011-01-14 17:55:32

标签: c# windows transactions editor binaryfiles

我正在为一些非常大的二进制文件创建二进制编辑器。其中一个软件要求是编辑器无法修改原始文件,因此目标文件必须是原始文件的编辑副本。

我想以这样的方式设计编辑器,即只复制文件一次(这将是一个20分钟的过程)。我知道我可以在编辑文件时锁定文件,但是如果用户退出程序,他们将不得不再次完成整个20分钟的复制过程,除非我能找到一种方法来确定它们仍在他们原来的编辑会议。

是否有一些您可以想到的简单过程我可以让用户以某种方式将复制的文件“注册”为可编辑文件,当它们完成所有更改后,“完成”文件?

理想情况下,这样的过程将允许我检测可编辑文件或交易信息是否已被篡改之间的编辑会话(篡改或终止会导致另一个副本发生,如果再次编辑文件。)

4 个答案:

答案 0 :(得分:1)

  1. 在集中位置创建并维护会话记录(db?)。
  2. 会话包括用户名,如果你已经拥有它,或IP,或者你想用来唯一识别用户的任何东西,以及字节的散列。如果散列对于文件大小来说太麻烦,您可以尝试依赖文件日期和大小。
  3. 当用户关闭其编辑器时,您使用上述信息更新会话记录并将其标记为非活动状态。
  4. 当用户重新打开编辑器时,您应该可以访问您的密钥信息,即用户名和文件信息。如果您找到会话记录,则可以重新激活该会话记录,否则,它将被篡改或全新。
  5. 这是否符合您的需求?

答案 1 :(得分:1)

我想你会想要记录用户采取的行动。为了避免写入源数据的副本,我会将日志保存在单独的文件中。使用时间戳信息存储用户的编辑。

当提交事务时,只需读取日志文件中的更改列表并应用它们,按时间戳排序。

当用户需要在编辑过程中从文件中读取数据时,您必须将源文件的相关部分读出到内存中,并将更改应用于日志文件中的数据。

这可能是最难的部分,具体取决于二进制文件格式。如果您能够以某种方式索引二进制文件的内容,我将在编辑日志中使用该信息。这样,您只能从日志文件中提取所需的数据,并且您将能够确定哪些编辑适用于该数据。

如果你拥有的只是一个庞大的无形blob,那么你必须将整个内容保存在内存中并在每次执行读取时应用所有更改。我认为,这里有优化的空间,但整个事情仍然非常令人发指。如果不能限制读取的范围,您必须假设任何编辑都可以随时更改任何数据。

至于确保编辑,这是一个棘手的问题。如果您在您信任的环境中运行,您可以保守秘密并使用它来验证信息。这很麻烦,但您可以散列二进制文件,编辑日志和仅为应用程序知道的秘密的串联。 (没有秘密,任何人都可以来,修改文件,并插入新的哈希。)

如果您在用户本地的计算机(即桌面)上运行,保密可能非常困难,尤其是对于托管代码。这本身就是一个话题,我没有给你一个好的答案。

答案 2 :(得分:1)

你不能只在该文件中有一个字段,在开始或结束的固定偏移处,你输入会话信息,只是一个'正在编辑'的标志?它可能包括对其当前编辑过程的引用(例如其pid)。如果pid是我们的pid,那么这就是我们的会话。如果它不是我们的pid,请查看进程列表。如果存在具有此pid的进程,则它是合法编辑器;如果没有,我们会看到崩溃的结果,启动崩溃恢复(如果有的话)。如果pid为0,则文件已完全确定。

另外:如果大文件可供阅读,你真的需要在编辑前复制吗?

如果编辑与文件大小相比相当小,我会将用户操作记录为原始文件和结果之间的“差异”。如果一次又一次地编辑相同的点,那么以某种方式“连接”差异可能是有用的,这样就不会应用太多的差异层。当然,用户对文件的看法是动态应用的所有差异。

在此期间,您复制文件,并且,一旦编辑会话结束文件完全在此处,您将所有差异应用于文件。但是,根据允许的编辑的性质,这可能是也可能不是一个耗时的过程。如果编辑会话超过20分钟,则用户可能根本没有注意到等待时间。您将在diff应用时锁定文件,这可能比复制时间短。

答案 3 :(得分:1)

由于您正在考虑事务和文件系统活动,因此考虑Transactional NTFS可能会有所帮助。这不能回答您的问题,但可能会让您对可能性有新的认识。由于您的问题已标记为C#和Windows,因此您可能需要查看.NET包装器,例如:http://offroadcoder.com/CategoryView,category,Transactions.aspx。 Scott Klueppel展示了如何利用TransactionScope熟悉的.NET习惯用法来处理事务性NTFS。我对斯科特所做的事情进行了快速测试,就像我所看到的一样。