我正在使用iTextSharp从PDF文件中读取文本。但是,有时我无法提取文本,因为PDF文件只包含图像。我每天都下载相同的PDF文件,我想看看PDF是否被修改过。如果无法获得文本和修改日期,MD5校验和是判断文件是否已更改的最可靠方法吗?

如果是的话,一些代码示例将受到赞赏,因为我在密码学方面没有太多经验。


当前回答

我知道这个问题已经有答案了,但我用的是:

using (FileStream fStream = File.OpenRead(filename)) {
    return GetHash<MD5>(fStream)
}

GetHash:

public static String GetHash<T>(Stream stream) where T : HashAlgorithm {
    StringBuilder sb = new StringBuilder();

    MethodInfo create = typeof(T).GetMethod("Create", new Type[] {});
    using (T crypt = (T) create.Invoke(null, null)) {
        byte[] hashBytes = crypt.ComputeHash(stream);
        foreach (byte bt in hashBytes) {
            sb.Append(bt.ToString("x2"));
        }
    }
    return sb.ToString();
}

可能不是最好的方法,但可以很方便。

其他回答

我知道我来晚了,但在实际实现解决方案之前进行了测试。

我确实对内置的MD5类和md5sum.exe进行了测试。在我的例子中,内置类花费了13秒,md5sum.exe每次运行大约16-18秒。

    DateTime current = DateTime.Now;
    string file = @"C:\text.iso";//It's 2.5 Gb file
    string output;
    using (var md5 = MD5.Create())
    {
        using (var stream = File.OpenRead(file))
        {
            byte[] checksum = md5.ComputeHash(stream);
            output = BitConverter.ToString(checksum).Replace("-", String.Empty).ToLower();
            Console.WriteLine("Total seconds : " + (DateTime.Now - current).TotalSeconds.ToString() + " " + output);
        }
    }

我知道这个问题已经有答案了,但我用的是:

using (FileStream fStream = File.OpenRead(filename)) {
    return GetHash<MD5>(fStream)
}

GetHash:

public static String GetHash<T>(Stream stream) where T : HashAlgorithm {
    StringBuilder sb = new StringBuilder();

    MethodInfo create = typeof(T).GetMethod("Create", new Type[] {});
    using (T crypt = (T) create.Invoke(null, null)) {
        byte[] hashBytes = crypt.ComputeHash(stream);
        foreach (byte bt in hashBytes) {
            sb.Append(bt.ToString("x2"));
        }
    }
    return sb.ToString();
}

可能不是最好的方法,但可以很方便。

除了上面回答的方法,如果你比较pdf,你需要修改创建日期和修改日期,否则哈希将不匹配。

对于用QuestPdf生成的pdf,你需要覆盖文档元数据中的CreationDate和ModifiedDate。

public class PdfDocument : IDocument
{
    ...

    DocumentMetadata GetMetadata()
    {
        return new()
        {
            CreationDate = DateTime.MinValue,
            ModifiedDate = DateTime.MinValue,
        };
    }
    
    ...
}

https://www.questpdf.com/concepts/document-metadata.html

用于动态生成的pdf。 创建日期和修改日期总是不同的。

你必须删除它们或将它们设置为一个常数值。

然后生成md5哈希来比较哈希。

您可以使用PDFStamper删除或更新日期。

我是这样做的:

using System.IO;
using System.Security.Cryptography;

public string checkMD5(string filename)
{
    using (var md5 = MD5.Create())
    {
        using (var stream = File.OpenRead(filename))
        {
            return Encoding.Default.GetString(md5.ComputeHash(stream));
        }
    }
}