C# 用于编辑大型二进制文件的事务模型

C# 用于编辑大型二进制文件的事务模型,c#,windows,transactions,editor,binaryfiles,C#,Windows,Transactions,Editor,Binaryfiles,我正在为一些非常大的二进制文件创建一个二进制编辑器。软件要求之一是编辑器无法修改原始文件,因此目标文件必须是原始文件的编辑副本 我想以这样一种方式设计编辑器:文件的复制只发生一次(这将是一个20分钟的过程)。我知道我可以在编辑文件时锁定该文件,但如果用户退出该程序,他们将不得不重新执行整个20分钟的复制过程,除非我能找到方法确定他们仍处于原始编辑会话中 你能想到一个简单的过程吗?通过这个过程,我可以允许用户以某种方式将复制的文件“注册”为可编辑文件,并在完成所有更改后“完成”文件 理想情况下,这

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

我想以这样一种方式设计编辑器:文件的复制只发生一次(这将是一个20分钟的过程)。我知道我可以在编辑文件时锁定该文件,但如果用户退出该程序,他们将不得不重新执行整个20分钟的复制过程,除非我能找到方法确定他们仍处于原始编辑会话中

你能想到一个简单的过程吗?通过这个过程,我可以允许用户以某种方式将复制的文件“注册”为可编辑文件,并在完成所有更改后“完成”文件

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

  • 在集中位置创建和维护会话记录(db?)
  • 会话由用户名(如果您有用户名的话)、IP或任何您想用来唯一标识用户的内容以及字节哈希组成。如果哈希对于文件大小来说太麻烦,您可以尝试依赖文件日期和大小
  • 当用户关闭其编辑器时,您将使用上述信息更新会话记录并将其标记为非活动
  • 当用户重新打开编辑器时,您应该可以访问您的关键信息,即用户名和文件信息。如果您找到一个会话记录,它是一个非活动会话,您可以重新激活它,否则,它要么被篡改,要么是全新的

  • 这是否符合您的需要?

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

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

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

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

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

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


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

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

    另外:如果大文件可以读取,您真的需要在编辑之前复制它吗

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


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

    < P>因为您正在考虑事务和文件系统活动,这可能有助于考虑事务性NTFS。这并不能回答你的问题,但可能会让你对可能性有一个新的认识。由于您的问题已标记为C#和Windows,因此您可能需要查看.NET包装,如以下所示:。Scott Klueppel展示了如何利用TransactionScope中熟悉的.NET习惯用法进行事务性NTFS。我对Scott所做的做了一个快速测试,并且很喜欢我所看到的。

    谢谢。事实证明,二进制文件格式中有一个标志,指示它是否为副本,所以我将翻转该标志。这不是可能被篡改的东西吗?是的,但它是文件规范的一部分,我不会让他们在我的编辑器中编辑它。谢谢。我考虑了一下“名单”