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

Я пытаюсь использовать различные функции файлов в С#, например File.GetLastWriteTime, скопировать команду в файл, помещенный на путь, который больше, чем максимально допустимый путь в Windows 7 i.e 260. Это дает мне ошибку при длинном имени пути. При поддержке MSDN я попросил использовать \\?\ до пути. Я сделал то же самое, но все же у меня такая же ошибка, похоже, она не вносит никаких изменений. Ниже мой код. Пожалуйста, дайте мне знать, если я использую его правильно или мне нужно добавить что-то: Все эти lib, которые я использую, также имеют код:

ниже приведен соответствующий код:

filesToBeCopied = Directory.GetFiles(path,"*",SearchOption.AllDirectories);
for (int j = 0; j < filesToBeCopied.Length; j++)
{
 try
 {
 String filepath = @"\\?\" + filesToBeCopied[j];
 File.GetLastWriteTime(filepath);
 }
 catch (Exception ex)
 {
 MessageBox.Show("Error Inside the single file iteration for the path:" +
 filesToBeCopied[j] + " . The exception is :" + ex.Message);
 }
}

где путь - путь к папке на машине Windows, начинающейся с буквы диска. например: d:\abc\bcd\cd\cdc\dc\..........

4 ответа

Вот решение, по крайней мере, для копии вашего запроса (спасибо pinvoke.net):

[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
static extern bool CopyFile(string lpExistingFileName, string lpNewFileName, bool bFailIfExists);

И затем, чтобы скопировать файл:

// Don't forget the '\\?\' for long paths
string reallyLongPath = @"\\?\d:\abc\bcd\cd\cdc\dc\..........";
string destination = @"C:\some\other\path\filename.txt";
CopyFile(reallyLongPath , destination, false);


Насколько я знаю, вы не можете получить доступ к файлу напрямую, если его путь слишком длинный (напрямую, я имею в виду использование методов File, создав FileInfo через конструктор или используя Directory.GetFiles(string fileName).

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

Я взял свой код и немного изменил его, чтобы вернуть объект FileInfo для файла с слишком длинным путем. Используя этот код, вы можете получить доступ к необходимым свойствам в возвращаемом объекте FileInfo (например, LastWriteTime). У него все еще есть некоторые ограничения, как, например, невозможность использования таких функций, как CopyTo() или OpenText().

// Only call GetFileWithLongPath() if the path is too long
// ... otherwise, new FileInfo() is sufficient
private static FileInfo GetFile(string path)
{
 if (path.Length >= MAX_FILE_PATH)
 {
 return GetFileWithLongPath(path);
 }
 else return new FileInfo(path);
}
static int MAX_FILE_PATH = 260;
static int MAX_DIR_PATH = 248;
private static FileInfo GetFileWithLongPath(string path)
{
 string[] subpaths = path.Split('\\');
 StringBuilder sbNewPath = new StringBuilder(subpaths[0]);
 // Build longest sub-path that is less than MAX_PATH characters 
 for (int i = 1; i < subpaths.Length; i++)
 {
 if (sbNewPath.Length + subpaths[i].Length >= MAX_DIR_PATH)
 {
 subpaths = subpaths.Skip(i).ToArray();
 break;
 }
 sbNewPath.Append("\\" + subpaths[i]);
 }
 ************* dir = new *************(sbNewPath.ToString());
 bool foundMatch = dir.Exists;
 if (foundMatch)
 {
 // Make sure that all of the subdirectories in our path exist. 
 // Skip the last entry in subpaths, since it is our filename. 
 // If we try to specify the path in dir.GetDirectories(), 
 // We get a max path length error. 
 int i = 0;
 while (i < subpaths.Length - 1 && foundMatch)
 {
 foundMatch = false;
 foreach (************* subDir in dir.GetDirectories())
 {
 if (subDir.Name == subpaths[i])
 {
 // Move on to the next subDirectory 
 dir = subDir;
 foundMatch = true;
 break;
 }
 }
 i++;
 }
 if (foundMatch)
 {
 // Now that we've gone through all of the subpaths, see if our file exists. 
 // Once again, If we try to specify the path in dir.GetFiles(), 
 // we get a max path length error. 
 foreach (FileInfo fi in dir.GetFiles())
 {
 if (fi.Name == subpaths[subpaths.Length - 1])
 {
 return fi;
 }
 }
 }
 }
 // If we didn't find a match, return null;
 return null;
}

Теперь, когда вы это видели, промойте глаза и сократите свои пути.


попробуйте с этим кодом

var path = Path.Combine(@"\\?\", filesToBeCopied[j]); //don't forget extension

"\? \" префикс строки пути сообщает API Windows отключить весь синтаксический разбор строки и отправить строку, которая следует за ней прямо в файловую систему.

Важно: не все API-интерфейсы ввода-вывода для файлов поддерживают "\? \", вы должны посмотреть справочную тему для каждого API


http://www.codinghorror.com/blog/2006/11/filesystem-paths-how-long-is-too-long.html

Недавно я импортировал некоторый исходный код для клиента, который превысил максимальный предел пути в 256 символов.

Путь, который вы вставляли, составлял 285 символов.

Как вы отметили в своем комментарии, ссылка MSDN здесь (http://msdn.microsoft.com/en-us/library/aa365247%28VS.85 % 29.aspx # maximum% 5Fpath% 5Flength) объясняет эту длину более подробно:

В API Windows (с некоторыми исключениями, описанными в следующих параграфах) максимальная длина для пути - MAX_PATH, которая определена как 260 символов. Локальный путь структурирован в следующем порядке: буква диска, двоеточие, обратная косая черта, компоненты имени, разделенные обратными косыми чертами, и завершающий нулевой символ. Например, максимальный путь на диске D представляет собой "D:\some 256-символьная строка пути", где "" представляет невидимый завершающий нулевой символ для текущей кодовой страницы системы. (Символы <> используются здесь для визуальной ясности и не могут быть частью допустимой строки пути.)

Что касается функциональности \\?\:

Многие, но не все API-интерфейсы ввода-вывода файлов поддерживают "\? \"; вы должны посмотреть на справочную тему для каждого API, чтобы быть уверенным.

licensed under cc by-sa 3.0 with attribution.