Сравнение файлов в C # - PullRequest
2 голосов
/ 23 марта 2009

Есть ли встроенный класс / метод для сравнения содержимого двух аудио / видео файлы? Или есть какой-либо встроенный класс / метод для преобразования аудио / видео файл в битовый поток?

Ответы [ 6 ]

3 голосов
/ 23 марта 2009

Другие ответы хороши - либо хэширование (если вы сравниваете файл с несколькими кандидатами), либо побайтовое сравнение (если сравниваете два отдельных файла).

Вот пара дополнительных мыслей:

Сначала проверьте размеры файлов - если они разные, не тратьте время на сравнение байтов. Это быстро проверить.

Во-вторых, попробуйте выполнить поиск в конце или середине файла, используя метод бинарной нарезки.

Например, предположим, у вас есть такой файл:

ABCDEFGHIJKLMNOP

Тогда это модифицируется так:

ABCDEF11GHIJKLMN

Если размер файла останется прежним, а содержимое будет вставлено, остальные байты будут "выбиты". Таким образом, бинарный подход может решить эту проблему с меньшим количеством операций чтения (например, при поиске и чтении байтов от SIZE / 2-10 до SIZE / 2 + 10 из обоих файлов и их сравнении).

Вы можете попытаться объединить приемы. Если вы сделаете это на достаточно хорошем образце данных, с которыми вы работаете, вы можете найти его для всех различных файлов, которые вы сравниваете (пример):

  • 80% было найдено, потому что размер файла был разным (10 мс на файл)
  • 10% были найдены из-за двоичной обработки (50 мс на файл)
  • 10% были найдены благодаря линейному сравнению байтов (2000 мс на файл)

Делать бинарную нарезку по всему файлу было бы не очень разумно, так как я ожидаю, что жесткий диск будет быстрее, если выполнять линейное чтение, а не искать случайные места. Но если вы проверяете SIZE / 2, затем SIZE / 4 + SIZE / 4x3, а затем SIZE / 8, скажем, для 5 итераций, вы можете найти большинство различий без необходимости выполнять байтовое сравнение. Просто несколько идей.

Кроме того, вместо чтения с начала файла, возможно, попробуйте прочитать с конца файла назад. Опять же, вы можете обменивать время поиска на вероятность, но в сценарии «вставка», предполагая, что в файл внесено изменение наполовину, вы, вероятно, найдете это быстрее, начиная с конца, чем с начала.

3 голосов
/ 23 марта 2009

Вы можете использовать хэш-функции в System.Security.Cryptography для двух файловых потоков и сравнивать их. Это легко сделать и хорошо работает с небольшими файлами. Если у вас большие файлы, которыми они, вероятно, являются, если вы имеете дело с аудио / видео, тогда чтение файла и генерация хеша могут занять некоторое время.

2 голосов
/ 05 февраля 2010

Пример: двоичное сравнение двух файлов

/// <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;
}
2 голосов
/ 23 марта 2009

Нет прямого способа сравнить файлы. И вам приходится иметь дело с аудио / видео файлами, которые будут относительно большими, я не знаю, побитовое сравнение будет работать или нет.

2 голосов
/ 23 марта 2009

Вы можете сделать байтовое сравнение двух файлов. System.IO.File.ReadAllBytes (...) было бы полезно для этого.

1 голос
/ 05 февраля 2010

Пример: создание хэшей SHA1 и MD5 в .NET (C #)

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;
}
...