【问题标题】:C# - Compare Two Text FilesC# - 比较两个文本文件
【发布时间】:2015-10-20 18:46:34
【问题描述】:

背景

我正在开发一个简单的 Windows 服务,它监视某些目录的文件创建事件并记录这些事件 - 长话短说,以确定文件是否从目录 A 复制到目录 B。如果X时间后文件不在目录B中,将引发警报。

与此有关的问题是,如果文件已进入目录 B,我只有在处理该文件时才能继续获取信息 - 我假设两个具有相同名称的文件是相同的,但因为有超过60 个目录 A 和一个目录 B - 并且任何目录 A 中的文件可能不小心与另一个目录相同(按日期或顺序),这不是一个安全的假设...

示例

假设,例如,我在目录 C:\Test 中存储了一个文件“E17999_XXX_2111.txt”创建的日志。我会存储此文件的文件名、文件路径、文件创建日期、文件长度和 BOM。

30 秒后,我检测到文件“E17999_XXX_2111.txt”是在目录 C:\FinalDestination... 中创建的...现在我的任务是确定是否;

a) 该文件与在 C:\Test 中创建的文件相同,因此我可以将第一个日志更新为完整并不再担心。

b) 文件不一样,我不知何故错过了前面的步骤 - 因此我可以忽略此文件,因为它已找到到达目标目录的方式。

研究

所以,为了确定目标中创建的文件是否与第一个实例中创建的文件完全相同,我做了一些研究,发现了以下选项:

a) 文件名比较

b) 长度比较

c) 创建日期比较

d) 逐字节比较

e) 哈希比较

问题

a) 正如我上面所说,仅使用文件名太冒昧了。

b) 同样,仅仅因为文件内容的长度相同,并不一定意味着文件实际上是相同的。

c) 这样做的问题是,复制文件在技术上是一个新文件,因此创建日期会发生变化。无论文件出现在目录 A 和目录 B 中经过多长时间,我都希望将第一个日志设置为完整。

d) 除了这个方法非常慢之外,如果第二个文件以某种方式改变了编码,就会出现问题——例如在 ANSII 和 ASCII 之间,这会导致 ascii 引号之类的字节不匹配

我不想假设仅仅因为 ASCII ' 已更改为 ANSII ',文件现在就不同了,因为它已经足够接近了。

e) 这似乎与逐字节比较具有相同的缺点

编辑

看来我遇到的实际问题归结为目录之间编码差异的原因 - 我目前无法访问处理这部分的代码,所以我不知道为什么会发生这种情况,但我正在寻求实现一种解决方案,该解决方案可以比较文件而不考虑编码以确定“真实”差异(即不是那些由于编码而导致字节改变的差异)

解决方案

如果@Magnus 建议的初始比较因此未能找到匹配项,我现在已设法解决此问题,方法是在对我的文件进行编码以删除任何错误数据后使用下面的 SequenceEqual 比较。代码如下:

byte[] bytes1 = Encoding.Convert(Encoding.GetEncoding(1252), Encoding.ASCII, Encoding.GetEncoding(1252).GetBytes(File.ReadAllText(FilePath))); 
byte[] bytes2 = Encoding.Convert(Encoding.GetEncoding(1252), Encoding.ASCII, Encoding.GetEncoding(1252).GetBytes(File.ReadAllText(FilePath))); 

if (Encoding.ASCII.GetChars(bytes1).SequenceEqual(Encoding.ASCII.GetChars(bytes2)))
    { 
    //matched! 
    } 

感谢您的帮助!

【问题讨论】:

  • 目前无法详细说明,但“慢”是相对的。 .net 框架非常擅长进行字符串比较,您可以将它们转换为原生字符串,这将是平等的。我会选择 A + B + D。按照这个顺序。每个人都取消了以后的失败测试。把它读成一个字符串来做 D
  • 改变的编码是一个真正会发生的问题吗?如果是这样,请确保它没有。
  • 我目前的概念使用 A + B + D,我认为它工作正常,直到遇到编码问题 - 我发现虽然在目录 A 中创建了一个文件,但“匹配”复制到目录 B 的文件略有不同 - 3 个字节变成了 1 个字节,因为 ASCII 字符引用已通过某种格式转换为另一种类型的引用。我还想匹配这些文件 - 这是我面临的真正问题:-)
  • @Magnus,它确实发生了,这完全出乎意料,我目前不知道是什么原因造成的,但当我尝试对各种代码库提供一种万能的解决方案时,我是希望能够提出一个解决方案,无论编码如何都能解决这个问题 - 我确实研究了如何确定文件的编码并找到了这个 stackoverflow.com/a/19283954/5468452 但无法找到一种方法将所有文件转换为比较的格式相同...有什么提示吗?
  • @DannyLager StreamReader 将自动检测使用的编码。

标签: c# .net winforms file compare


【解决方案1】:

然后您必须比较文件中的字符串内容。 StreamReaderReadLines 使用)应该检测编码。

var areEquals = System.IO.File.ReadLines("c:\\file1.txt").SequenceEqual(
                System.IO.File.ReadLines("c:\\file2.txt"));

注意ReadLines 不会将整个文件读入内存。

【讨论】:

  • 谢谢,如果可能的话,我会试一试,在我们比较两个字符串文字时,无论编码如何,它都会返回 true,还是与逐字节比较一样?
  • 刚刚尝试解决我遇到的问题,对两者都使用 UTF8 编码 - File.ReadLines(FilePath1, Encoding.UTF8).SequenceEqual(File.ReadLines(FilePath2, Encoding.UTF8)) - 这将返回错误,但文件中唯一的区别是引用,所以我假设这个仍然把它扔掉......关于如何解决这个问题的任何建议?这是一个非常快速的运行,这是一个积极的......
  • 也许引号字符实际上是不同的,这不是编码问题。
  • 原来我必须重新读取这两个文件,然后在进行上述比较之前将它们转换为 ASCII 编码,如果我发现初始比较失败。
猜你喜欢
  • 2011-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多