我希望以这样的方式设计编辑器,即只进行一次文件复制(这将需要20分钟时间)。我知道可以在编辑文件时锁定文件,但如果用户退出程序,则必须重新进行整个20分钟的复制过程,除非我能找到一种方法来确定他们仍处于原始编辑会话中。
您能否想到一些简单的流程,使用户可以以某种方式“注册”已复制的文件作为可编辑文件,并在完成所有更改后“完成”文件?
理想情况下,这种流程将允许我在编辑会话之间检测可编辑文件或事务信息是否被篡改(如果再次编辑文件,则篡改或完成将导致另一个复制)。
这符合您的需求吗?
我认为您需要记录用户执行的操作。为了避免写入源数据的副本,我会将日志保存在单独的文件中。使用时间戳信息存储用户的编辑。
当提交事务时,只需读取日志文件中更改列表并按时间戳顺序应用它们即可。
当用户在编辑过程中需要从文件中读取数据时,您需要将源文件的相关部分读入内存,并从日志文件中应用更改到该数据。
这可能是最难的部分,具体取决于二进制文件格式。如果您有能力以某种方式索引二进制文件的内容,则可以在编辑日志中使用该信息。这样,您可以仅从日志文件中提取所需的数据,并确定哪些编辑适用于该数据。
如果您只有一个大而无形的块,则必须将整个块保留在内存中,并在每次执行读取时应用所有更改。我认为这里有优化的空间,但整个过程仍然非常恶劣。如果无法限制读取范围,则必须假定任何编辑都可能随时更改任何数据。
关于保护编辑内容的安全性,这是一个棘手的问题。如果您正在运行一个值得信任的环境,您可以保持一个秘密并使用它来验证信息。虽然这很麻烦,但您可以对二进制文件、编辑日志和应用程序所知道的秘密进行连接哈希。(没有这个秘密,任何人都可以修改文件并插入新的哈希)。
如果您在用户本地机器上运行(例如桌面),保持秘密会非常困难,特别是对于托管代码。这是一个单独的主题,我无法给您一个好的答案。
你能不能在文件中添加一个字段,从开头或结尾的固定偏移量处,存储会话信息,比如“正在编辑”的标志?它可以包括对当前编辑进程(例如其pid)的引用。如果pid是我们的pid,则这是我们的会话。如果不是我们的pid,则查看进程列表。如果存在具有此pid的进程,则它是合法的编辑器;否则,我们正在看到崩溃的结果,启动崩溃恢复(如果有)。如果pid为0,则文件已经干净地完成了。
另外:如果大文件可供阅读,您真的需要在编辑之前将其复制吗?
如果编辑相对于文件大小而言较小,我会将用户操作记录为原始文件和结果之间的“差异”。如果同一位置反复编辑,可能有必要以某种方式“合并”这些差异,以便不会应用太多层差异。当然,用户对文件的视图是动态应用所有差异后的结果。
同时,您复制文件,并且一旦编辑会话结束并且文件完全到位,您将所有差异应用于该文件。根据允许的编辑性质,这可能是一个耗时的过程,也可能不是。如果编辑会话超过20分钟,用户可能根本不会注意到等待时间。您将锁定文件以进行差异应用,这个过程预计比复制时间短。既然您正在考虑事务和文件系统活动,可能考虑Transactional NTFS会有所帮助。这并不回答您的问题,但可能会让您对可能性有一个新的见解。既然您的问题被标记为C#和Windows,您可能想查看一个.NET包装器,例如此处:http://offroadcoder.com/CategoryView,category,Transactions.aspx。Scott Klueppel展示了如何利用熟悉的.NET习语TransactionScope执行Transactional NTFS。我对Scott所做的测试进行了快速测试,并喜欢我所看到的。