Каков наилучший способ объединить путь и имя файла в С#/.NET?

Каков наилучший способ объединить путь с именем файла?

То есть, учитывая c:\foo и bar.txt, я хочу c:\foo\bar.txt.

Учитывая c:\foo и ..\bar.txt, я хочу либо ошибку, либо c:\foo\bar.txt (поэтому я не могу использовать Path.Combine() напрямую). Точно так же для c:\foo и bar/baz.txt мне нужна ошибка или c:\foo\baz.txt (не c:\foo\bar\baz.txt).

Я понимаю, я мог бы проверить, что имя файла не содержит '\' или '/', но достаточно ли этого? Если нет, то какова правильная проверка?


person Rasmus Faber    schedule 26.06.2009    source источник


Ответы (3)


Если вы хотите, чтобы «плохие» имена файлов вызывали ошибку:

if (Path.GetFileName(fileName) != fileName)
{
    throw new Exception("'fileName' is invalid!");
}
string combined = Path.Combine(dir, fileName);

Или, если вы просто хотите тихо исправить «плохие» имена файлов, не вызывая исключения:

string combined = Path.Combine(dir, Path.GetFileName(fileName));
person LukeH    schedule 26.06.2009
comment
Для тех, кто менее знаком с фреймворком, вам нужен вызов using System.IO; в вашем файле, чтобы получить доступ к Path. - person Robert Gowland; 07.09.2012
comment
Обратите внимание, что Path.Combine выдаст ArgumentNullException, если любой из его аргументов равен null. Вы можете передать пустую строку любому аргументу - person Aaron Blenkush; 02.03.2013
comment
Примечание. Path.Combine обычно добавляет разделитель между каждым путем, если это необходимо. Однако Path.Combine(C:, file.txt) возвращает C:file.txt, что не является допустимым путем. - person ConditionRacer; 26.07.2014

Вы можете использовать:

Path.Combine(folder, Path.GetFileName(fileName))

или, чтобы пропустить \ (не проверено, возможно, Path.GetFileName обрабатывает это автоматически)

Path.Combine(folder, Path.GetFileName(fileName.Replace("/","\\")))
person GvS    schedule 26.06.2009
comment
Спасибо! Просто к вашему сведению: Замена не нужна. - person Rasmus Faber; 26.06.2009

Имейте в виду, что когда вы используете Path.Combine(arg1, arg2) - если ваш пользователь вводит полный путь к файлу для arg2, он будет игнорировать arg1 и использовать arg2 в качестве пути.

По-моему, Майкрософт тут накосячил! Это может оставить вас открытыми для пользователя, взломавшего всю вашу файловую систему. Будьте осторожны, читайте мелкий шрифт! Если вы комбинируете пути, используйте: var newPath = path1 + @"\" + path2; проще и без неожиданных результатов...

person Ravi    schedule 02.06.2015
comment
Полный путь с правой стороны, возвращаемый в результате объединения относительных путей, является правильным и действительным результатом. - person Matthew Whited; 21.06.2015
comment
Независимо от того, является ли это правильным и действительным результатом, слишком много разработчиков упускают из виду тот факт, что если в их коде arg1 — это путь к папке, а arg2 — ввод пользователя, то в результате будет получен абсолютный путь, введенный arg2. На мой взгляд, слишком легко открыться для худших взломов веб-приложений ... кода / инъекции оболочки ... Проверьте свой ввод, ребята. - person Cyassin; 08.08.2016
comment
На мой взгляд, любой разработчик, который считает нормальным позволять пользователю вводить пути без какой бы то ни было проверки, заслуживает того, чтобы его взломали. Это материал первого дня, и Path.Combine не предназначен для работы так, как вы думаете, - это достойный и надежный способ избежать проверки обратной косой черты терминала, которая на самом деле предназначена для внутреннего использования вашим кодом, не как интерфейс для защиты ваших файлов. Документация для него достаточно полная — просто прочтите ее. - person jinzai; 19.12.2017