2010-06-05 3 views
4

У меня есть MemoryStream, содержащий байты изображения с PNG-кодированием, и вы хотите проверить, есть ли точный дубликат этих данных изображения в каталоге на диске. Первым очевидным шагом является поиск файлов, соответствующих точной длине, но после этого я хотел бы узнать, что является наиболее эффективным способом сравнения памяти с файлами. Я не очень опытен, работая с потоками.Самый эффективный способ сравнения memystream с файлом C# .NET

У меня было пару мыслей по этому вопросу:

во-первых, если я мог бы получить хэш-код для файла, он будет (предположительно) будет более эффективным для сравнения хэш-кодов, а не каждый байт изображения. Аналогично, я мог бы сравнить только некоторые байты изображения, давая ответ «достаточно близко».

А потом, конечно, я мог бы просто сравнить весь поток, но я не знаю, как бы быстро это было.

Каков наилучший способ сравнить MemoryStream с файлом? Байт по-байту в цикле?

+0

«... искать файлы, соответствующие точной длине ...«Внимание: размер файла на диске, возможно, будет отличаться от размера потока ... Дисковый файл может иметь встроенную миниатюру, которой нет в потоке памяти ... Файлы изображений могут быть немного goofy вот так :) – Rusty

+0

В моем случае я создаю файлы изображений на диске тоже, так что это должно быть безопасно? – devios1

+0

Да FileStream.Length == FileInfo.Length ... но если вы используете Image.FromFile и сохраните его к MemoryStream они не будут иметь одинаковую длину ... я обычно работаю с объектами Image, следовательно, моя забота. – Rusty

ответ

9

Во-первых, получение хэш-кода двух потоков не поможет - для расчета хэш-кодов вам нужно будет прочитать все содержимое и выполнить простые вычисления при чтении. Если вы сравниваете файлы по байтам или с помощью буферов, вы можете остановить ранее (после того, как вы найдете первые два байта/блока), которые не совпадают.

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

В любом случае вам необходимо написать код, чтобы прочитать весь файл. Как вы уже упоминали, это можно сделать побайтовым или с использованием буферов. Чтение данных в буфер - хорошая идея, потому что это может быть более эффективная работа при чтении с жесткого диска (например, чтение буфера 1 кБ). Более того, вы можете использовать асинхронный метод BeginRead, если вам нужно обрабатывать несколько файлов параллельно.

Резюме:

  • Если вам нужно сравнить несколько файлов, используйте Hashcode
  • Для чтения/сравнения содержимого одного файла:
    • Читать 1kB данных в буфер из обоих потоки
    • Посмотрите, есть ли разница (если да, прекратите)
    • Продолжить цикл

Выполнить вышеуказанные действия асинхронно с помощью BeginRead, если вам нужно обработать mutliple файлы параллельно.

+0

Важно знать (маловероятную) возможность хеш-коллизий.Бутовое сравнение было бы необходимо, чтобы избежать этой проблемы. –

+0

Так что, чтобы быть ясным, я бы прочитал 1 kb куски из файла в буфер, а затем сравнил те buf байт по байтам байта? – devios1

+1

BufferedStream как оболочка для FileStream должен заботиться о проблеме буферизации. – sunside

18

Другое решение:

private static bool CompareMemoryStreams(MemoryStream ms1, MemoryStream ms2) 
{ 
    if (ms1.Length != ms2.Length) 
     return false; 
    ms1.Position = 0; 
    ms2.Position = 0; 

    var msArray1 = ms1.ToArray(); 
    var msArray2 = ms2.ToArray(); 

    return msArray1.SequenceEqual(msArray2); 
} 
+0

В значительной степени память критическая, но отлично подходит для моих потребностей в небольших потоках. ;) – cmxl

+0

Почему вы устанавливаете Position = 0? Документация MemoryStream.ToArray() гласит: «Записывает содержимое потока в массив байтов, независимо от свойства Position». –

+0

Просто привычка, я полагаю, от бит-бит, устанавливая позицию перед работой над потоком. – CodeMonkey1313

-4

Использование Stream мы не получим результат, каждый файлов имеет уникальный идентификатор, например, дату последнего изменения и так далее. Таким образом, каждый файл отличается. Эта информация включена в поток

+0

Если вы читаете файл с потоком, вы читаете его содержимое, а не метаданные, хранящиеся в файловой системе. Также этот вопрос особенно касается сравнения содержимого файлов. – sloth

Смежные вопросы