在Windows上处理文本文件

我有多个Windows程序(在Windows 2000,XP和7上运行),处理不同格式(csv,tsv,ini和xml)的文本文件。 在文件IO期间不要损坏这些文件的内容是非常重要的。 每个文件应该可以安全地由多个程序同时访问,并且应该能够抵抗系统崩溃。 这个答案build议使用进程内数据库,所以我正在考虑使用Microsoft Jet数据库引擎 ,它能够处理分隔文本文件 (csv,tsv),并支持事务 。 我之前使用过Jet,但是我不知道Jet事务是否真的能容忍在提交阶段意外崩溃或closures,我不知道如何处理非分隔文本文件(ini,xml)。 我不认为这是一个好主意,试图手工实现完整的ACIDic文件IO。

在Windows上实现文本文件事务处理的最佳方式是什么? 我必须能够在Delphi和C#中做到这一点。

提前谢谢你的帮助。

编辑

让我们来看一个基于@ SirRufo的想法的例子。 忘记一秒钟的并发性,让我们专注于崩溃容忍。

  1. 我将一个文件的内容读入一个数据结构中,以便修改一些字段。 当我正在将修改后的数据写回到文件中时,系统可能会崩溃。

  2. 如果我从不将数据写回原始文件,可以避免文件损坏。 这可以很容易地通过创build一个新的文件来实现,每次保存修改时在文件名中加上一个时间戳。 但这还不够:原始文件将保持不变,但新写入的文件可能已损坏。

  3. 我可以通过在时间戳之后加一个“0”来解决这个问题,这意味着文件还没有被validation。 我将通过validation步骤结束写入过程:我将读取新文件,将其内容与我试图保存的内存结构进行比较,如果它们相同,则将标志更改为“1”。 每次程序读取文件时,都会通过比较文件名中的时间戳来select最新的版本。 只有最新版本必须保留,旧版本可以删除。

  4. 在读取或写入文件之前,可以通过等待已命名的互斥锁来处理并发性。 当一个程序获得对该文件的访问时,它必须从检查文件名列表开始。 如果它想读取文件,它将读取最新版本。 另一方面,只有当没有比上次读取的版本更新的版本时才能开始写入。

这是一个粗略的,简单的,低效率的方法,但它显示了我在想什么。 写文件是不安全的,但也许有一些简单的技巧,如上面的,可以帮助避免文件损坏。

UPDATE

用Java编写的开源解决scheme:

  • primefaces文件事务: 文章-1 , 文章-2 , 源代码
  • Javaprimefaces文件事务(JAFT): 项目主页
  • XADisk: 教程 , 源代码
  • AtomicFile: 描述 , 源代码

如何使用NTFS文件流? 将多个已命名(编号/时间戳)的流写入相同的文件名。 每个版本都可以存储在不同的流中,但实际上存储在同一个“文件”或一堆文件中,保留数据并提供回滚机制…当您到达确定点时,删除一些先前的流。

在NT 4中引入? 它涵盖所有版​​本。 应该是崩溃证明你将永远有以前的版本/流加原来恢复/回滚到。

只是一个深夜的想法。

http://msdn.microsoft.com/en-gb/library/windows/desktop/aa364404%28v=vs.85%29.aspx

你所要求的是事务性,如果没有根据你的需求发展自己的RDBMS数据库的机制,这是不可能的:

“在文件IO期间不要损坏这些文件的内容是非常重要的”

拿起一个DBMS。

查看相关文章使用多个线程访问单个文件但是我的意见是使用像Raven DB这样的数据库来处理这些类型的事务,Raven DB支持对同一个文件的并发访问,并支持将多个操作的批处理支持到一个请求中。 但是,一切都保持为JSON文件,而不是文本文件。 它确实支持.NET / C#,包括Javascript和HTML,但不支持Delphi。

首先这个问题与C#或Delphi没有任何关系。 你必须仿真你的文件结构,就好像它是一个数据库一样。

假设;

  • 移动文件是一个便宜的过程,操作系统保证文件在移动过程中不被破坏。

  • 您有一个需要处理的文件的单个目录。 (d:\ filesDB *。*)

  • 控制器应用程序是必须的。

简化工作流程;

-初始化

  1. 从操作系统获取一个processID。
  2. 在d:\ filesDB中创建目录

     d:\filesDB\<processID> d:\filesDB\<processID>\inBox d:\filesDB\<processID>\outBox 

每个文件的进程

  1. 选择要处理的文件。
  2. 将其移动到“收件箱”目录(确保单一访问文件)
  3. 打开文件
  4. 在“outBox”中创建新文件并正确关闭
  5. 删除“收件箱”目录中的文件。
  6. 将位于“OutBox”中的新创建的文件移回到d:\ filesDB

-finallization

  1. 删除创建的目录。

控制器应用

只在系统启动时运行,并初始化将完成工作的应用程序。

  1. 扫描d:\ filesDB目录中的子目录,
  2. 对于每个子目录2.1,如果文件存在于“inBox”中,将其移动到d:\ filesDB并跳过“outBox”。 2.2如果文件存在于“outBox”中,将其移动到d:\ filesDB 2.3删除整个子目录。
  3. 启动每个需要启动的工作进程。

我希望这会解决你的问题。

好吧,你已经死了 – 除非你可以放弃XP。 那么简单

由于POST-XP Windows支持事务性NTFS,尽管它不会暴露给.NET(本机 – 你仍然可以使用它)。 这允许在NTFS文件系统上回滚或提交更改,即使与数据库配合使用DTC。 很不错。 XP,但是 – 没办法,不在那里。

从交易型NTFS(TxF)的任何现实世界的企业级经验开始? 作为首发。 那里的问题列出了很多资源,让你开始如何做到这一点。

请注意,这显然会带来性能开销。 不过,除非您需要第二个事务资源,因为这里有一个非常简单的内核级事务协调器,所以在添加第二个资源时,事务只会被提升到完整的DTC。

直接链接 – http://msdn.microsoft.com/en-us/magazine/cc163388.aspx有一些很好的信息&#x3002;

您正在为您自己创建一个恶梦,尝试处理这些交易,并在您自己的代码中跨越多个系统。 这就是为什么Larry Ellison(甲骨文首席执行官)是亿万富翁,我们大多数人不是。 如果您绝对必须使用文件,请设置支持LOB和CLOB对象的Oracle或其他数据库。 我为我的公司在这样的表格中存储了非常大的SVG文件,这样我们就可以在没有任何代码更改的情况下向我们的系统添加和渲染大型地图。 这些文件可以从表中提取出来,并在缓冲区中传递给用户,然后在完成时返回到数据库。 设置适当的安全和记录锁定,并解决您的问题。