Какой самый быстрый способ получения списков файлов и многократного поиска по спискам файлов? - PullRequest
0 голосов
/ 16 ноября 2011

Какой самый быстрый способ получения списков файлов и многократного поиска по спискам файлов?

Положение:

  1. На сетевом диске может быть от 5000 до 35 000 файлов, распределенных по 3-5 корневым каталогам (которые имеют много подкаталогов).
  2. Существует три типа файлов (tif, sus, img), которые пользователь может искать или не искать. Некоторые типы файлов могут иметь 2-3 различных расширения файлов.
  3. Из списка файлов (в разных таблицах базы данных) мне нужно выяснить, существует ли каждый файл, и если он существует, сохранить только путь и имя файла только в таблице.
  4. Поиск по именам файлов должен выполняться с учетом регистра, но было бы неплохо сохранить исходный регистр при сохранении пути к таблице.

Окружающая среда:

C # и .NET 4.0 на ПК с Windows.

Это самый быстрый способ?:

Является ли самый быстрый способ использования словаря с FileName в качестве ключа (строчные буквы) и Path в качестве значения (исходный регистр)? Таким образом, я могу получить индекс / путь на том же проходе, когда я ищу имя файла? FileName и Path разделяются спереди при заполнении списка.

if (d.TryGetValue("key", out value))
{
    // Log "key" and value to table  // only does one lookup
}

Примечание: я немного обеспокоен тем, что у меня, вероятно, будут одинаковые значения ключа для каждого типа файла Когда / Если я столкнусь с этим сценарием, какой тип списка и метод доступа мне следует использовать?

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

Ответы [ 2 ]

1 голос
/ 16 ноября 2011

Я бы использовал Dictionary<string,string> с FullName (путь + файл + ext), измененным на строчные буквы в качестве ключа и FullName без изменений в качестве значения.Затем разбейте необходимые части, используя статические методы GetDirectoryName и GetFileName класса System.IO.Path, прежде чем вставлять их в таблицу.

РЕДАКТИРОВАТЬ : метод GetFilesDirectoryInfo класс возвращает массив FileInfo.FileInfo имеет свойство FullName, возвращающее путь + файл + доп.Вы также можете сохранить это значение FileInfo в качестве значения в своем словаре, если потребление памяти не является проблемой.FileInfo имеет свойства DirectoryName и Name, возвращающие две необходимые вам части.

EDIT : Вот моя реализация мультикарты, которая выполняет Directory<TKey,List<TValue>>:

/// <summary>
/// Represents a collection of keys and values. Multiple values can have the same key.
/// </summary>
/// <typeparam name="TKey">Type of the keys.</typeparam>
/// <typeparam name="TValue">Type of the values.</typeparam>
public class MultiMap<TKey, TValue> : Dictionary<TKey, List<TValue>>
{

    public MultiMap()
        : base()
    {
    }

    public MultiMap(int capacity)
        : base(capacity)
    {
    }

    /// <summary>
    /// Adds an element with the specified key and value into the MultiMap. 
    /// </summary>
    /// <param name="key">The key of the element to add.</param>
    /// <param name="value">The value of the element to add.</param>
    public void Add(TKey key, TValue value)
    {
        List<TValue> valueList;

        if (TryGetValue(key, out valueList)) {
            valueList.Add(value);
        } else {
            valueList = new List<TValue>();
            valueList.Add(value);
            Add(key, valueList);
        }
    }

    /// <summary>
    /// Removes first occurence of a element with a specified key and value.
    /// </summary>
    /// <param name="key">The key of the element to remove.</param>
    /// <param name="value">The value of the element to remove.</param>
    /// <returns>true if the a element is removed; false if the key or the value were not found.</returns>
    public bool Remove(TKey key, TValue value)
    {
        List<TValue> valueList;

        if (TryGetValue(key, out valueList)) {
            if (valueList.Remove(value)) {
                if (valueList.Count == 0) {
                    Remove(key);
                }
                return true;
            }
        }
        return false;
    }

    /// <summary>
    /// Removes all occurences of elements with a specified key and value.
    /// </summary>
    /// <param name="key">The key of the elements to remove.</param>
    /// <param name="value">The value of the elements to remove.</param>
    /// <returns>Number of elements removed.</returns>
    public int RemoveAll(TKey key, TValue value)
    {
        List<TValue> valueList;
        int n = 0;

        if (TryGetValue(key, out valueList)) {
            while (valueList.Remove(value)) {
                n++;
            }
            if (valueList.Count == 0) {
                Remove(key);
            }
        }
        return n;
    }

    /// <summary>
    /// Gets the total number of values contained in the MultiMap.
    /// </summary>
    public int CountAll
    {
        get
        {
            int n = 0;

            foreach (List<TValue> valueList in Values) {
                n += valueList.Count;
            }
            return n;
        }
    }

    /// <summary>
    /// Determines whether the MultiMap contains a element with a specific key / value pair.
    /// </summary>
    /// <param name="key">Key of the element to search for.</param>
    /// <param name="value">Value of the element to search for.</param>
    /// <returns>true if the element was found; otherwise false.</returns>
    public bool Contains(TKey key, TValue value)
    {
        List<TValue> valueList;

        if (TryGetValue(key, out valueList)) {
            return valueList.Contains(value);
        }
        return false;
    }

    /// <summary>
    /// Determines whether the MultiMap contains a element with a specific value.
    /// </summary>
    /// <param name="value">Value of the element to search for.</param>
    /// <returns>true if the element was found; otherwise false.</returns>
    public bool Contains(TValue value)
    {
        foreach (List<TValue> valueList in Values) {
            if (valueList.Contains(value)) {
                return true;
            }
        }
        return false;
    }

}
0 голосов
/ 16 ноября 2011

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

Помните, что вы также можете использовать объект FileWatcher для синхронизации словаря / списка памяти с содержимым диска, если он может быть изменен. Если он статичен, я, вероятно, сохраню все это в таблице базы данных и выполню поиск, при котором запуск вашей программы будет мгновенным.

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

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