Возвращение словаря <FileHash, string []> из запроса Linq - PullRequest
0 голосов
/ 25 сентября 2010

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

Dictionary<FileHash, string[]> FindDuplicateFiles(string searchFolder)
{
    Directory.GetFiles(searchFolder, "*.*")
        .Select(
            f => new
                     {
                         FileName = f,
                         FileHash = Encoding.UTF8.GetString(new SHA1Managed()
                                                                .ComputeHash(new FileStream(f,
                                                                                            FileMode.
                                                                                                OpenOrCreate,
                                                                                            FileAccess.Read)))
                     })
        .GroupBy(f => f.FileHash)
        .Select(g => new
                         {
                             FileHash = g.Key,
                             Files = g.Select(z => z.FileName).ToList()
                         })
        .GroupBy(f => f.FileHash)
        .Select(g => new {FileHash = g.Key, Files = g.Select(z => z.Files).ToArray()});

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

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

Ответы [ 3 ]

0 голосов
/ 25 сентября 2010

Вы можете использовать Enumerable.ToDictionary , чтобы собрать запрос LINQ в словарь:

var sha1 = new SHA1Managed();

Dictionary<string, string[]> result =
    Directory
        .EnumerateFiles(searchFolder)
        .GroupBy(file => Convert.ToBase64String(sha1.ComputeHash(...)))
        .ToDictionary(g => g.Key, g => g.ToArray());

Некоторые замечания:

  • Не предполагайте, что случайная последовательность байтов (например, хэш SHA-1) является допустимой строкой UTF-8.
  • Попробуйте использовать Directory.EnumerateFiles вместо Directory.GetFiles.
  • Не забудьте закрыть FileStream после вычисления хэша SHA-1.
  • Afaik, можно повторно использовать SHA1Managed, поэтому вам не нужно создавать новый для каждого файла.
0 голосов
/ 25 сентября 2010

Уже есть метод расширения, который сделает это.Просто добавьте это в конец вашего существующего запроса:

.ToDictionary(x => x.FileHash, x => x.Files);

Однако: использование Encoding.UTF8.GetString для преобразования произвольных двоичных данных в строку - действительно плохая идея.Вместо этого используйте Convert.ToBase64String.Хеш не строка в кодировке UTF-8, поэтому не рассматривайте ее как единое целое.

Вы также группируете по хешу дважды, что, как я подозреваю, на самом деле не то, что выхочу сделать.

Либо удалите предыдущие вызовы GroupBy и используйте вместо него Lookup:

var query = Directory.GetFiles(searchFolder, "*.*")
                     .Select(f => new {
                         FileName = f,
                         FileHash = Convert.ToBase64String(
                             new SHA1Managed().ComputeHash(...))
                        })
                     .ToLookup(x => x.FileHash, x => x.FileName);

Это даст вам Lookup<string, string>, который в основном представляет собой файлысгруппированы по хешу.

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

var query = Directory.GetFiles(searchFolder)
                     .ToLookup(x => ComputeHash(x));

Трудно упростить его гораздо дальше, чем это:)

0 голосов
/ 25 сентября 2010

Создайте метод расширения для IEnumerable <_> с именем toDictionary, который преобразует последовательность пар значений ключа в словарь. Может вызвать исключение для дубликатов ключей.

Зачем вам второй GroupBy?

...