Как удалить недопустимые символы из пути и имен файлов? - PullRequest
394 голосов
/ 28 сентября 2008

Мне нужен надежный и простой способ удаления недопустимых путей и символов файла из простой строки. Я использовал приведенный ниже код, но он, похоже, ничего не делает, что мне не хватает?

using System;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string illegal = "\"M<>\"\\a/ry/ h**ad:>> a\\/:*?\"<>| li*tt|le|| la\"mb.?";

            illegal = illegal.Trim(Path.GetInvalidFileNameChars());
            illegal = illegal.Trim(Path.GetInvalidPathChars());

            Console.WriteLine(illegal);
            Console.ReadLine();
        }
    }
}

Ответы [ 26 ]

457 голосов
/ 28 сентября 2008

Попробуйте что-то вроде этого;

string illegal = "\"M\"\\a/ry/ h**ad:>> a\\/:*?\"| li*tt|le|| la\"mb.?";
string invalid = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());

foreach (char c in invalid)
{
    illegal = illegal.Replace(c.ToString(), ""); 
}

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

Редактировать: Или потенциально «лучшее» решение с использованием регулярных выражений.

string illegal = "\"M\"\\a/ry/ h**ad:>> a\\/:*?\"| li*tt|le|| la\"mb.?";
string regexSearch = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
Regex r = new Regex(string.Format("[{0}]", Regex.Escape(regexSearch)));
illegal = r.Replace(illegal, "");

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

254 голосов
/ 20 апреля 2014
public string GetSafeFilename(string filename)
{

    return string.Join("_", filename.Split(Path.GetInvalidFileNameChars()));

}

Этот ответ был в другой ветке от Ceres , мне очень нравится это аккуратно и просто.

203 голосов
/ 13 сентября 2011

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

private static string CleanFileName(string fileName)
{
    return Path.GetInvalidFileNameChars().Aggregate(fileName, (current, c) => current.Replace(c.ToString(), string.Empty));
}

Обновление

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

https://dotnetfiddle.net/nw1SWY

86 голосов
/ 24 ноября 2010

Вы можете удалить недопустимые символы с помощью Linq следующим образом:

var invalidChars = Path.GetInvalidFileNameChars();

var invalidCharsRemoved = stringWithInvalidChars
.Where(x => !invalidChars.Contains(x))
.ToArray();

EDIT
Вот как это выглядит с необходимой правкой, указанной в комментариях:

var invalidChars = Path.GetInvalidFileNameChars();

string invalidCharsRemoved = new string(stringWithInvalidChars
  .Where(x => !invalidChars.Contains(x))
  .ToArray());
26 голосов
/ 16 ноября 2011

Это отличные решения, но все они основаны на Path.GetInvalidFileNameChars, что может быть не так надежно, как вы думаете. Обратите внимание на следующее замечание в документации MSDN по Path.GetInvalidFileNameChars:

Массив, возвращаемый этим методом, не обязательно содержит полный набор символов, недопустимых в именах файлов и каталогов. Полный набор недопустимых символов может варьироваться в зависимости от файловой системы. Например, на настольных платформах под управлением Windows недопустимые символы пути могут включать символы ASCII / Unicode от 1 до 31, а также кавычки ("), меньше чем (<), больше чем (>), pipe (|), backspace ( \ b), ноль (\ 0) и табуляция (\ t).

Не лучше с Path.GetInvalidPathChars методом. Он содержит точно такое же замечание.

19 голосов
/ 11 февраля 2014

Для имен файлов:

string cleanFileName = String.Join("", fileName.Split(Path.GetInvalidFileNameChars()));

Для полных путей:

string cleanPath = String.Join("", path.Split(Path.GetInvalidPathChars()));

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

18 голосов
/ 28 сентября 2008

Для начала, Обрезка удаляет только символы из начала или конца строки . Во-вторых, вы должны оценить, действительно ли вы хотите удалить оскорбительные символы или быстро потерпеть неудачу и сообщить пользователю, что их имя файла недействительно. Мой выбор - последний, но мой ответ должен, по крайней мере, показать вам, как правильно и неправильно поступить:

Вопрос StackOverflow, показывающий, как проверить, является ли данная строка действительным именем файла . Обратите внимание, что вы можете использовать регулярное выражение из этого вопроса, чтобы удалить символы с заменой регулярного выражения (если вам действительно нужно это сделать).

16 голосов
/ 28 сентября 2008

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

string regex = string.Format(
                   "[{0}]",
                   Regex.Escape(new string(Path.GetInvalidFileNameChars())));
Regex removeInvalidChars = new Regex(regex, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.CultureInvariant);

Тогда я просто вызываю removeInvalidChars.Replace, чтобы выполнить поиск и замену. Очевидно, это можно расширить и на символы пути.

15 голосов
/ 28 сентября 2013

Лучший способ удалить недопустимый символ из пользовательского ввода - заменить недопустимый символ с помощью класса Regex, создать метод в коде или также проверить его на стороне клиента с помощью элемента управления RegularExpression.

public string RemoveSpecialCharacters(string str)
{
    return Regex.Replace(str, "[^a-zA-Z0-9_]+", "_", RegexOptions.Compiled);
}

OR

<asp:RegularExpressionValidator ID="regxFolderName" 
                                runat="server" 
                                ErrorMessage="Enter folder name with  a-z A-Z0-9_" 
                                ControlToValidate="txtFolderName" 
                                Display="Dynamic" 
                                ValidationExpression="^[a-zA-Z0-9_]*$" 
                                ForeColor="Red">
14 голосов
/ 15 февраля 2011

Я абсолютно предпочитаю идею Джеффа Йейтса. Это будет отлично работать, если вы немного измените его:

string regex = String.Format("[{0}]", Regex.Escape(new string(Path.GetInvalidFileNameChars())));
Regex removeInvalidChars = new Regex(regex, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.CultureInvariant);

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

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