C#-比较两个文本文件

C#-比较两个文本文件,c#,.net,winforms,file,compare,C#,.net,Winforms,File,Compare,背景 我正在开发一个简单的windows服务,它监视某些目录中的文件创建事件并记录这些事件(长话短说),以确定文件是否从目录a复制到目录B。如果文件在X时间后不在目录B中,将发出警报 这个问题是,当我计算它是否已进入目录B时,我只有文件可供参考-我假设两个同名文件是相同的,但有60多个目录A和一个目录B-并且任何目录A中的文件可能意外地与另一个目录相同(按日期或顺序)这不是一个安全的假设 示例 比方说,我存储了一个日志文件“E17999_XXX_2111.txt”是在目录C:\Test中创建的。

背景

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

这个问题是,当我计算它是否已进入目录B时,我只有文件可供参考-我假设两个同名文件是相同的,但有60多个目录A和一个目录B-并且任何目录A中的文件可能意外地与另一个目录相同(按日期或顺序)这不是一个安全的假设

示例

比方说,我存储了一个日志文件“E17999_XXX_2111.txt”是在目录C:\Test中创建的。我会存储文件名、文件路径、文件创建日期、文件长度和该文件的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! 
    } 

谢谢你的帮助

然后,如果文件不正确,则必须比较字符串内容。
StreamReader
ReadLines
使用的)应该检测编码

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

请注意,
ReadLines
不会将完整的文件读入内存。

现在无法详细说明,但“slow”是相对的。net framework非常擅长进行字符串比较,您可以将它们转换为本机字符串,这将是平等的。我会按照A+B+d的顺序去做。如果失败,每个人都会取消以后的测试资格。把它当作一个字符串来读,这样就可以改变编码,这才是真正会发生的问题?如果是这样的话,请确保它没有。我当前的概念使用A+B+D,我认为它工作得很好,直到我遇到编码问题-我发现虽然在目录A中创建了一个文件,但复制到目录B中的“匹配”文件却有微小的不同-3个字节变为1个字节,因为ASCII字符引号已通过某种格式转换为另一种类型的引号。我希望仍然匹配这些文件-这是我面临的真正问题:-)@Magnus,它确实发生了,这完全出乎意料,我目前不知道是什么原因造成的,但我正在尝试一种适用于各种代码库的一刀切的解决方案,我希望能够找到一种解决方案,无论编码如何,都能解决这个问题-我确实研究了如何确定文件的编码,发现了这个问题,但无法找到一种方法将所有文件转换为相同的格式用于比较。。。有什么提示吗?@DannyLager
StreamReader
将自动检测所使用的编码。谢谢,如果可能的话,我会尝试一下,当我们比较两个字符串文本时,不管编码如何,这会返回真值吗?还是会与逐字节比较相同?只是尝试一下我遇到的问题,对-File.ReadLines(FilePath1,Encoding.UTF8).SequenceEqual(File.ReadLines(FilePath2,Encoding.UTF8))和-File.ReadLines(FilePath2,Encoding.UTF8)都使用UTF8编码-这返回的是false,但文件中唯一的区别是引号,所以我假设这仍然会抛出它。。。有没有关于如何解决这个问题的建议?这是非常快的运行,这是一个积极的…也许引号字符实际上是不同的,它不是一个编码问题。结果表明,我必须重新读取这两个文件,然后将它们转换为ASCII编码,然后再做上述比较,如果我发现最初的比较