dabbourabd Ответов: 3

Ошибка Fileinfo " слишком длинный путь"


привет всем

Я пытаюсь получить информацию о файлах в указанном каталоге

поэтому я использую этот код
string path = @"D:\Directory";
            string[] filepathes = Directory.GetFiles(path, ".", SearchOption.AllDirectories);
            var items = from f in filepathes
                        select new ListViewItem(
                            new string[] {
                            new FileInfo(f).Directory.ToString(),
                            new FileInfo(f).Name.ToString(),
                            new FileInfo(f).CreationTime.ToString(),
                            new FileInfo(f).Length.ToString()});


но я получил ошибку
- Указанный путь, имя файла или и то и другое слишком длинны. Полное имя файла должно быть не более 260 символов, а имя каталога-не более 248 символов."

Я знаю, что эта ошибка возникает, когда путь к файлу слишком длинный

но мой вопрос есть ли способ избежать этой ошибки


благодарить всех

[no name]

Избежать ошибки? Конечно, не делайте слишком длинные имена путей. Вы можете поймать ошибку и игнорировать ее....

3 Ответов

Рейтинг:
24

Zoltán Zörgő

Это ограничение функций API, которые вызывает платформа .net framework. Это не означает, что Windows или .net не могут обрабатывать такие длинные имена файлов. Просто встроенные инструменты ограничены. Стыдно, но это все :(
Есть библиотеки, которые вы можете использовать. Подобный этому:
http://zetalongpaths.codeplex.com/[^]
http://bcl.codeplex.com/wikipage?title=Long%20Path&referringTitle=домой[^]
http://gallery.technet.microsoft.com/DelimonWin32IO-Library-V40-7ff6b16c[^]
Просто заметка: они могут быть не совсем полными. Я предлагаю вам поискать больше, попробовать столько, сколько сможете, и найти наиболее подходящее для вас.


Рейтинг:
14

Ian A Davidson

Способ получения информации о файлах с слишком длинным именем-это P/Invoke to the Windows API. Я считаю, что это то, что библиотеки, которые Золтан has linked to will be doing under the hood (на самом деле первый даже ссылается на некоторые страницы об этом), поэтому я не буду добавлять к этой информации здесь.

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

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

Кроме того, вы создаете FileInfo для каждого файла четыре раза. Я считаю, что каждый экземпляр будет кэшировать многие свойства файла при построении, так что это будет неоправданно медленно. (См. примечание в примерах FileInfo[^])

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

Боюсь, что я ничего не знаю о синтаксисе "select", который вы использовали, поэтому, если бы я переделал это, я бы, вероятно, сделал что-то вроде этого:

string path = @"D:\Directory";
string[] filePaths = Directory.GetFiles(path, ".", SearchOption.AllDirectories);
foreach (string f in filePaths)
{
  try
  {
    FileInfo info = new FileInfo(f);
    ListViewItem item = new ListViewItem(new string[] {
      info.DirectoryName,         // Note use of this instead of Directory.ToString() !!
      info.Name.ToString(),
      info.CreationTime.ToString(),
      info.Length.ToString()});
    // Do what you need to do with "item"
  }
  catch(PathTooLongException)
  {
    // Ignore, or add listview item to report error, or
    // do something to try to get the information
    // (e.g. P/Invoke to the Windows API).
    // Note since you already have the full path name, you could use
    // System.IO.Path to get the directory and file name.
    // E.g.
    ListViewItem item = new ListViewItem(new string[] {
      Path.GetDirectoryName(f),
      Path.GetFileName(f),
      "Path too long",   /* Error message in "Created Time" field.  This is only an example, you probably don't want to do this in real application! Maybe have an additional "error" field? */
      ""});
    // Do what you need to do with "item"
  }
  catch(SecurityException)
  {
    // Ignore, or add listview item reporting permission denied, as above.
  }
  catch(UnauthorizedAccessException)
  {
    // Ignore, or add listview item reporting permission denied, as above.
  }
}

С уважением,
Иан.


Рейтинг:
1

dabbourabd

большое спасибо всем

как сказал Золтан Зерго я использовал

Delimon.Win32.IO.dll библиотека вместо системы.Ио и это сработало отлично

окончательный код таков :

string path = @"D:\books";
            string[] filepathes = System.IO.Directory.GetFiles(path, ".", System.IO.SearchOption.AllDirectories);
var items = from f in filepathes
select new ListViewItem(
new string[] {
new Delimon.Win32.IO.FileInfo(f).Directory.FullName, // Directory
new Delimon.Win32.IO.FileInfo(f).Name.ToString(), // Name
new Delimon.Win32.IO.FileInfo(f).CreationTime.ToString(),
new Delimon.Win32.IO.FileInfo(f).Length.ToString()});