Самый эффективный способ сравнить поток памяти с файлом C # .NET - PullRequest
7 голосов
/ 05 июня 2010

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

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

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

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

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

Ответы [ 4 ]

20 голосов
/ 19 февраля 2012

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

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);
}
10 голосов
/ 05 июня 2010

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

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

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

Сводка :

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

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

0 голосов
/ 12 июня 2019

Мы открыли библиотеку с источниками, чтобы справиться с этим в NeoSmart Technologies, потому что нам пришлось сравнивать непрозрачные Stream объекты для байтового равенства один раз слишком много. Он доступен на NuGet как StreamCompare, и вы можете прочитать о его преимуществах перед существующими подходами в официальном объявлении о выпуске .

Использование очень просто:

var stream1 = ...;
var stream2 = ...;

var scompare = new StreamCompare();
var areEqual = await scompare.AreEqualAsync(stream1, stream2);

Он написан для отвлечения как можно большего числа ошибок и ошибок производительности и содержит ряд оптимизаций для ускорения сравнений (и минимизации использования памяти). В пакет также включена оболочка сравнения файлов FileCompare, которую можно использовать для сравнения двух файлов по пути.

StreamCompare выпущен под лицензией MIT и работает на .NET Standard 1.3 и выше. Доступны пакеты NuGet для .NET Standard 1.3, .NET Standard 2.0, .NET Core 2.2 и .NET Core 3.0. Полная документация находится в файле README.

0 голосов
/ 12 июля 2013

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...