【问题标题】:Generating an MD5 value for a file using StreamReader and Readline()使用 StreamReader 和 Readline() 为文件生成 MD5 值
【发布时间】:2014-11-25 20:42:31
【问题描述】:

好的。在这个论坛上,我的问题的不同方面已经被多次询问和回答。但是,我认为从未有人问过我对这个问题的特殊变体。所以,就这样吧。我试图为同一个文本文件生成两个哈希值,以便在处理之前和处理之后比较数据文件。这个点小脑筋的目的是验证整个文件是否已经被程序读取和处理过。

我已经向自己证明,使用字节和数组将文件分成大块,然后使用 MD5.TransformBlock 将创建一个 has 值(该程序代码遍布整个网络)。而且,当我运行我的程序时,两个哈希值是相同的。但是,我使用 StreamReader 的 readline() 方法一次读取一行文本文件,这会生成不正确的哈希值。

伪代码是:

BufferedStream reader = OpenFile(file)
string initialMd5 = generateMd5FromBufferedStream(reader)

//Start from the beginning again
reader.setposition = 0
reader.DiscardBufferedData();

while((tmpLine = reader.readline()) != null ) {
    Byte() buffer = GetBytes(tmpLine);
    md5.TransformBlock(buffer, 0, buffer.length, 0)
}

md5.TransformFinal(buffer, 0, 0);
String finalMd5 = ConvertToString(md5.Hash());

有什么想法吗?我对如何解决这个问题的想法已经不多了。

提前致谢!!

【问题讨论】:

  • 你为什么要涉及字符串?您应该直接阅读流。
  • 也许 readline 正在删除行尾。如何处理带有 0x0(可能最后多次)的字符串?要验证这一点,只需读取一行并将其写入另一个文件 - 这应该会导致两个文件包含相同的内容,对吧? - 然后比较这两个文件,您可能会发现差异。
  • 如何计算从输入中读取的字节数?由于 0x0 值,只有直接从输入读取的函数才能正常工作。
  • ReadLine 当然不包括行尾,没有“可能”。

标签: c# md5 readline


【解决方案1】:

这不是已发布问题的答案,但检查文件的上次访问或修改日期以检测更改是否不够? .Net 在 System.IO 命名空间中有一个 FileInfo 类,具有 LastAccessTime 和 LastWriteTime 的属性。

【讨论】:

  • 这不会回答前后文件是否相同的问题
【解决方案2】:

所以,正如我在原始帖子中提到的原因,使用 readline 创建哈希的原因,以便在读取和处理文件时生成哈希。想法是如果读取和处理文件后的哈希值与原始哈希值相同,那么我可以确信整个文件已被处理。

我们遇到了 StreamReader.ReadLine() 没有读取整个文件的情况。由于某种原因,它只是在文件中间切断。虽然行为是随机的。而且,更糟糕的是,没有出现任何错误!讨厌的 .NET!

无论如何,我的问题的答案是,当 readline 方法将字节数组(即文件中的一行文本)转换为字符串时,它会从字节数组中添加和减去“东西”来执行转换.因此,经过大量研究工作,答案似乎是在使用 StreamReader.ReadLine 读取文件时无法生成准确的哈希。

现在,如果有人对为什么这个愚蠢的东西停止读取中间文件有任何想法......

【讨论】:

    【解决方案3】:

    这是我们目前正在使用的。

    用法:

    using (StreamReader file = new StreamReader(filepath))
    {
        // store checksum
        Checksum = file.BaseStream.ToMD5Hash(); 
        ....
    }
    

    扩展方法:

    public static string ToMD5Hash(this System.IO.Stream stream)
    {
        string hash = string.Empty;
        long position = stream.Position;
    
        // Initialize a hash object
        using (System.Security.Cryptography.MD5 myHasher = System.Security.Cryptography.MD5.Create())
        {
            // Be sure it's positioned to the beginning of the stream
            stream.Position = 0;
    
            // Compute the hash of the stream and convert to a string
            hash = myHasher.ComputeHash(stream).ByteArrayToString();
        }
    
        // reset location
        stream.Position = position;         
    
        return hash;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-19
      • 1970-01-01
      • 1970-01-01
      • 2012-03-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多