繁体   English   中英

C#中的文件比较

[英]File comparison in C#

是否有任何内置类/方法来比较两个音频/视频文件的内容? 或者是否有任何内置类/方法将音频/视频文件转换为位 stream?

您可以在两个文件流上使用 System.Security.Cryptography 中的 hash 函数并进行比较。 这很容易做到,并且适用于小文件。 如果您的文件很大,如果您正在处理音频/视频,则可能是这样,那么读取文件并生成 hash 可能需要一些时间。

其他答案很好 - 散列(如果您将文件与多个候选者进行比较)或逐字节比较(如果比较两个单个文件)。

以下是一些额外的想法:

首先,检查文件大小——如果它们不同,那么不要浪费时间比较字节。 这些可以快速检查。

其次,尝试使用二分法从文件的末尾或中间进行搜索。

例如,假设你有一个这样的文件:

ABCDEFGHIJKLMNOP

然后修改成这样:

ABCDEF11GHIJKLMN

为了使文件大小保持不变,并且要插入内容,其他字节将被“剔除”。 因此,二进制切分方法可能会以更少的读取来解决这个问题(例如,从两个文件中查找和读取字节 SIZE/2-10 到 SIZE/2+10,并进行比较)。

你可以尝试结合这些技术。 如果您对所处理的数据的足够好的样本进行此操作,您可能会发现您比较的所有不同文件(示例):

  • 80% 被发现是因为文件大小不同(每个文件 10ms)
  • 10% 被发现是由于二进制斩波(每个文件 50 毫秒)
  • 由于线性字节比较(每个文件 2000 毫秒)发现了 10%

对整个文件进行二进制切碎不会那么聪明,因为我希望如果线性读取而不是寻找随机点,硬盘会更快。 但是,如果您检查 SIZE/2,然后是 SIZE/4+SIZE/4x3,然后是 SIZE/8,例如 5 次迭代,您可能会发现大部分差异,而无需进行逐字节比较。 只是一些想法。

另外,不是从文件的前面读取,而是尝试从文件的末尾向后读取。 同样,您可能会用寻找时间来换取概率,但在“插入”场景中,假设在文件中途进行了更改,您可能会发现从末尾开始比从头开始更快。

示例:2 个文件的二进制比较

/// <summary>
/// Methode, die einen Binärvergleich von 2 Dateien macht und
/// das Vergleichsergebnis zurückliefert.
/// </summary>
/// <param name="p_FileA">Voll qualifizierte Pfadangabe zur ersten Datei.</param>
/// <param name="p_FileB">Voll qualifizierte Pfadangabe zur zweiten Datei.</param>
/// <returns>True, wenn die Dateien binär gleich sind, andernfalls False.</returns>
private static bool FileDiffer(string p_FileA, string p_FileB)
{
    bool retVal = true;
    FileInfo infoA = null;
    FileInfo infoB = null;
    byte[] bufferA = new byte[128];
    byte[] bufferB = new byte[128];
    int bufferRead = 0;

    // Die Dateien überprüfen
    if (!File.Exists(p_FileA))
    {
        throw new ArgumentException(String.Format("Die Datei '{0}' konnte nicht gefunden werden", p_FileA), "p_FileA");
    }
    if (!File.Exists(p_FileB))
    {
        throw new ArgumentException(String.Format("Die Datei '{0}' konnte nicht gefunden werden", p_FileB), "p_FileB");
    }

    // Dateiinfo wegen der Dateigröße erzeugen
    infoA = new FileInfo(p_FileA);
    infoB = new FileInfo(p_FileB);

    // Wenn die Dateigröße gleich ist, dann einen Vergleich anstossen
    if (infoA.Length == infoB.Length)
    {
        // Binärvergleich
        using (BinaryReader readerA = new BinaryReader(File.OpenRead(p_FileA)))
        {
            using (BinaryReader readerB = new BinaryReader(File.OpenRead(p_FileB)))
            {
                // Dateistream blockweise über Puffer einlesen
                while ((bufferRead = readerA.Read(bufferA, 0, bufferA.Length)) > 0)
                {
                    // Dateigrößen sind gleich, deshalb kann hier
                    // ungeprüft auch von der 2. Datei eingelesen werden
                    readerB.Read(bufferB, 0, bufferB.Length);

                    // Bytevergleich innerhalb des Puffers
                    for (int i = 0; i < Math.Min(bufferA.Length, bufferRead); i++)
                    {
                        if (bufferA[i] != bufferB[i])
                        {
                            retVal = false;
                            break;
                        }
                    }

                    // Wenn Vergleich bereits fehlgeschlagen, dann hier schon abbruch
                    if (!retVal)
                    {
                        break;
                    }
                }
            }
        }
    }
    else
    {
        // Die Dateigröße ist schon unterschiedlich
        retVal = false;
    }

    return retVal;
}

您可以对这两个文件进行逐字节比较。 System.IO.File.ReadAllBytes(...) 将对此有用。

没有直接的方法来比较文件。 而且您必须处理音频/视频文件,这些文件会比较大,我不知道按位比较是否有效。

示例:在 .NET (C#) 中生成 SHA1 和 MD5 哈希

public static string GenerateHash(string filePathAndName)
{
  string hashText = "";
  string hexValue = "";

  byte[] fileData = File.ReadAllBytes(filePathAndName);
  byte[] hashData = SHA1.Create().ComputeHash(fileData); // SHA1 or MD5

  foreach (byte b in hashData)
  {
    hexValue = b.ToString("X").ToLower(); // Lowercase for compatibility on case-sensitive systems
    hashText += (hexValue.Length == 1 ? "0" : "") + hexValue;
  }

  return hashText;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM