Как удалить недопустимые символы из пути и имен файлов?

352

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

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();
        }
    }
}
  • 0
    Trim удаляет символы из начала и конца строк. Тем не менее, вы, вероятно, должны спросить, почему данные являются недействительными, и вместо того, чтобы пытаться санировать / исправить данные, отклонить данные.
  • 8
    Имена стилей Unix недопустимы в Windows, и я не хочу иметь дело с 8.3 короткими именами.
Показать ещё 3 комментария
Теги:
directory
string
path

26 ответов

414
Лучший ответ

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

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(), ""); 
}

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

Изменить: Или потенциально "лучшее" решение, используя Regex's.

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, "");

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

  • 1
    Я не знаю, стоит ли мне +1 ваш ответ за то, что у меня есть такое неэффективное решение, которое оттолкнет пользователя от этого пути, или мне нужно +1 ваш ответ за то, что он действительно отвечает на его вопрос! :)
  • 0
    Интересно, является ли regex-replace более производительным здесь?
Показать ещё 22 комментария
222
public string GetSafeFilename(string filename)
{

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

}

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

  • 8
    Чтобы точно ответить на вопрос ОП, вам нужно будет использовать «» вместо «_», но ваш ответ, вероятно, относится к большинству из нас на практике. Я думаю, что замена нелегальных символов некоторыми легальными делается чаще.
  • 4
    Это фантастический ответ. Я не знаю о производительности, но это очень легко читать и понимать.
Показать ещё 5 комментариев
191

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

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

Update

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

https://dotnetfiddle.net/nw1SWY

  • 4
    Это не сработало для меня. Метод не возвращает чистую строку. Он возвращает переданное имя файла как есть.
  • 0
    Что @Karan сказал, это не работает, оригинальная строка возвращается.
Показать ещё 5 комментариев
79

Вы можете удалить незаконные символы, используя Linq, как это:

var invalidChars = Path.GetInvalidFileNameChars();

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

ИЗМЕНИТЬ
Вот как это выглядит с требуемым правлением, упомянутым в комментариях:

var invalidChars = Path.GetInvalidFileNameChars();

string invalidCharsRemoved = new string(stringWithInvalidChars
  .Where(x => !invalidChars.Contains(x))
  .ToArray());
  • 1
    Мне нравится этот способ: вы сохраняете в строке только разрешенные символы (которые есть не что иное, как массив символов).
  • 5
    Я знаю, что это старый вопрос, но это потрясающий ответ. Тем не менее, я хотел добавить, что в c # вы не можете приводить из char [] к строковым значениям либо неявно, либо явно (без ума, я знаю), поэтому вам нужно поместить его в строковый конструктор.
Показать ещё 4 комментария
27

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

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

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

  • 12
    Тогда в чем смысл Path.GetInvalidFileNameChars? Я ожидаю, что он вернет точно недопустимые символы для текущей системы, полагаясь на .NET, чтобы узнать, на какой файловой системе я работаю, и предоставив мне подходящие неверные символы. Если это не так, и он просто возвращает жестко закодированные символы, которые, во-первых, ненадежны, этот метод следует удалить, поскольку он имеет нулевое значение.
  • 1
    Я знаю, что это старый комментарий, но @Jan вы можете написать в другой файловой системе, может быть, поэтому есть предупреждение.
Показать ещё 4 комментария
18

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

https://stackoverflow.com/questions/62771/how-do-i-check-if-a-given-string-is-a-legal-valid-file-name-under-windows. Обратите внимание, что вы можете использовать регулярное выражение из этого вопроса для удаления символов с заменой регулярного выражения (если вам действительно нужно это сделать).

  • 0
    Я особенно согласен со вторым советом.
  • 3
    Обычно я соглашусь со вторым, но у меня есть программа, которая генерирует имя файла и в некоторых ситуациях может содержать недопустимые символы. Поскольку моя программа генерирует недопустимые имена файлов, я думаю, что целесообразно удалить / заменить эти символы. (Просто указывает на действительный вариант использования)
16

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

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

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

string cleanPath = String.Join("", path.Split(Path.GetInvalidPathChars()));
  • 0
    Очень хитрое и интеллектуальное решение! Палец вверх
15

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

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

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

  • 0
    Этот код не работает по какой-то причине.
  • 0
    Странно, это работает на меня. Я проверю это дважды, когда получу шанс. Можете ли вы быть более конкретным и объяснить, что именно не работает для вас?
Показать ещё 3 комментария
14

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

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

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

  • 0
    Но твой код такой же, как у Джеффса ?!
  • 1
    Он изменил свой ответ после того, как я опубликовал это исправление.
13

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

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

ИЛИ

<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">
  • 4
    ИМХО, это решение намного лучше, чем другие. Вместо поиска всех недопустимых символов просто определите, какие из них действительны.
  • 0
    Хорошее решение +1
11

Вот фрагмент кода, который должен помочь для .NET 3 и выше.

using System.IO;
using System.Text.RegularExpressions;

public static class PathValidation
{
    private static string pathValidatorExpression = "^[^" + string.Join("", Array.ConvertAll(Path.GetInvalidPathChars(), x => Regex.Escape(x.ToString()))) + "]+$";
    private static Regex pathValidator = new Regex(pathValidatorExpression, RegexOptions.Compiled);

    private static string fileNameValidatorExpression = "^[^" + string.Join("", Array.ConvertAll(Path.GetInvalidFileNameChars(), x => Regex.Escape(x.ToString()))) + "]+$";
    private static Regex fileNameValidator = new Regex(fileNameValidatorExpression, RegexOptions.Compiled);

    private static string pathCleanerExpression = "[" + string.Join("", Array.ConvertAll(Path.GetInvalidPathChars(), x => Regex.Escape(x.ToString()))) + "]";
    private static Regex pathCleaner = new Regex(pathCleanerExpression, RegexOptions.Compiled);

    private static string fileNameCleanerExpression = "[" + string.Join("", Array.ConvertAll(Path.GetInvalidFileNameChars(), x => Regex.Escape(x.ToString()))) + "]";
    private static Regex fileNameCleaner = new Regex(fileNameCleanerExpression, RegexOptions.Compiled);

    public static bool ValidatePath(string path)
    {
        return pathValidator.IsMatch(path);
    }

    public static bool ValidateFileName(string fileName)
    {
        return fileNameValidator.IsMatch(fileName);
    }

    public static string CleanPath(string path)
    {
        return pathCleaner.Replace(path, "");
    }

    public static string CleanFileName(string fileName)
    {
        return fileNameCleaner.Replace(fileName, "");
    }
}
8

В большинстве решений выше сочетаются незаконные символы для обоих путей и имени файла, что неверно (даже если оба вызова в настоящее время возвращают один и тот же набор символов). Сначала я разделил бы путь + имя файла в пути и имя файла, затем применил бы соответствующий набор к ним, если они есть, а затем снова объединить два.

wvd_vegt

  • 0
    +1: очень верно. Сегодня, работая в .NET 4.0, решение regex из верхнего ответа уничтожило все обратные косые черты в полном пути. Поэтому я сделал регулярное выражение для пути dir и регулярное выражение только для имени файла, очищенное отдельно и повторно объединенное
  • 0
    Это может быть правдой, но это не отвечает на вопрос. Я не уверен, что расплывчатое «я бы сделал это так» ужасно полезно по сравнению с некоторыми из уже готовых решений (см., Например, ответ Лилли ниже)
6

Если вы удалите или замените одним символом недопустимые символы, вы можете столкнуться с ошибками:

<abc -> abc
>abc -> abc

Вот простой способ избежать этого:

public static string ReplaceInvalidFileNameChars(string s)
{
    char[] invalidFileNameChars = System.IO.Path.GetInvalidFileNameChars();
    foreach (char c in invalidFileNameChars)
        s = s.Replace(c.ToString(), "[" + Array.IndexOf(invalidFileNameChars, c) + "]");
    return s;
}

Результат:

 <abc -> [1]abc
 >abc -> [2]abc
5

Выбросьте исключение.

if ( fileName.IndexOfAny(Path.GetInvalidFileNameChars()) > -1 )
            {
                throw new ArgumentException();
            }
4

Я написал это чудовище для удовольствия, он позволяет вам совершать кругооборот:

public static class FileUtility
{
    private const char PrefixChar = '%';
    private static readonly int MaxLength;
    private static readonly Dictionary<char,char[]> Illegals;
    static FileUtility()
    {
        List<char> illegal = new List<char> { PrefixChar };
        illegal.AddRange(Path.GetInvalidFileNameChars());
        MaxLength = illegal.Select(x => ((int)x).ToString().Length).Max();
        Illegals = illegal.ToDictionary(x => x, x => ((int)x).ToString("D" + MaxLength).ToCharArray());
    }

    public static string FilenameEncode(string s)
    {
        var builder = new StringBuilder();
        char[] replacement;
        using (var reader = new StringReader(s))
        {
            while (true)
            {
                int read = reader.Read();
                if (read == -1)
                    break;
                char c = (char)read;
                if(Illegals.TryGetValue(c,out replacement))
                {
                    builder.Append(PrefixChar);
                    builder.Append(replacement);
                }
                else
                {
                    builder.Append(c);
                }
            }
        }
        return builder.ToString();
    }

    public static string FilenameDecode(string s)
    {
        var builder = new StringBuilder();
        char[] buffer = new char[MaxLength];
        using (var reader = new StringReader(s))
        {
            while (true)
            {
                int read = reader.Read();
                if (read == -1)
                    break;
                char c = (char)read;
                if (c == PrefixChar)
                {
                    reader.Read(buffer, 0, MaxLength);
                    var encoded =(char) ParseCharArray(buffer);
                    builder.Append(encoded);
                }
                else
                {
                    builder.Append(c);
                }
            }
        }
        return builder.ToString();
    }

    public static int ParseCharArray(char[] buffer)
    {
        int result = 0;
        foreach (char t in buffer)
        {
            int digit = t - '0';
            if ((digit < 0) || (digit > 9))
            {
                throw new ArgumentException("Input string was not in the correct format");
            }
            result *= 10;
            result += digit;
        }
        return result;
    }
}
  • 1
    Мне нравится это, потому что это позволяет избежать двух разных строк, создающих один и тот же путь.
3

Я думаю, что гораздо легче проверить использование регулярного выражения и указать, какие символы разрешены, вместо того, чтобы пытаться проверить все плохие символы. См. Следующие ссылки: http://www.c-sharpcorner.com/UploadFile/prasad_1/RegExpPSD12062005021717AM/RegExpPSD.aspx http://www.windowsdevcenter.com/pub/a/oreilly/windows/news/csharp_0101.html

Кроме того, выполните поиск в редакторе регулярных выражений, они многое помогут. Есть некоторые, вокруг которых даже вывести код в С# для вас.

  • 0
    Учитывая, что .net - это фреймворк, предназначенный для запуска программ на нескольких платформах (например, Linux / Unix, а также Windows), я считаю, что Path.GetInvalidFileNameChars () лучше, поскольку он будет содержать сведения о том, что есть или нет. Не действует в файловой системе, в которой выполняется ваша программа. Даже если ваша программа никогда не будет работать в Linux (возможно, она полна кода WPF), всегда есть вероятность, что в будущем появится какая-то новая файловая система Windows с другими действительными / недействительными символами. Свернуть свое собственное с помощью регулярных выражений - это заново изобрести колесо и перенести проблему с платформой в свой собственный код.
  • 0
    Я согласен с вашим советом по редакторам / тестерам онлайн-регулярных выражений. Я нахожу их бесценными (поскольку регулярные выражения - это хитрые вещи, полные тонкости, которые могут легко сбить вас с толку, давая вам регулярное выражение, которое ведет себя каким-то дико неожиданным образом с крайними случаями). Мой фаворит - regex101.com (мне нравится, как он разбивает регулярное выражение и ясно показывает, что он должен соответствовать). Мне также очень нравится debuggex.com, так как он имеет компактное визуальное представление групп совпадений и классов символов и еще много чего.
2
public static class StringExtensions
      {
        public static string RemoveUnnecessary(this string source)
        {
            string result = string.Empty;
            string regex = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
            Regex reg = new Regex(string.Format("[{0}]", Regex.Escape(regex)));
            result = reg.Replace(source, "");
            return result;
        }
    }

Вы можете использовать метод четко.

2

Сканирование по ответам здесь, все они **, похоже, связаны с использованием массива char недопустимых имен файлов.

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

В прошлом я был очень удивлен (потрясен), насколько быстро хешсет (или словарь) превосходит итерирование по списку. Со строками это смехотворно низкое число (около 5-7 предметов из памяти). С большинством других простых данных (ссылки на объекты, числа и т.д.) Магический кроссовер, кажется, составляет около 20 элементов.

В списке Path.InvalidFileNameChars имеется 40 недопустимых символов. Был ли поиск сегодня и там довольно хороший тест здесь, на StackOverflow, который показывает, что hashset займет чуть более половины времени массива/списка для 40 элементов: https://stackoverflow.com/questions/150750/hashset-vs-list-performance

Здесь класс-помощник, который я использую для дезинфекции путей. Я забыл, почему у меня появился вариант замены, но он там как милый бонус.

Дополнительный бонусный метод "IsValidLocalPath" тоже:)

(** те, которые не используют регулярные выражения)

public static class PathExtensions
{
    private static HashSet<char> _invalidFilenameChars;
    private static HashSet<char> InvalidFilenameChars
    {
        get { return _invalidFilenameChars ?? (_invalidFilenameChars = new HashSet<char>(Path.GetInvalidFileNameChars())); }
    }


    /// <summary>Replaces characters in <c>text</c> that are not allowed in file names with the 
    /// specified replacement character.</summary>
    /// <param name="text">Text to make into a valid filename. The same string is returned if 
    /// it is valid already.</param>
    /// <param name="replacement">Replacement character, or NULL to remove bad characters.</param>
    /// <param name="fancyReplacements">TRUE to replace quotes and slashes with the non-ASCII characters " and ⁄.</param>
    /// <returns>A string that can be used as a filename. If the output string would otherwise be empty, "_" is returned.</returns>
    public static string ToValidFilename(this string text, char? replacement = '_', bool fancyReplacements = false)
    {
        StringBuilder sb = new StringBuilder(text.Length);
        HashSet<char> invalids = InvalidFilenameChars;
        bool changed = false;

        for (int i = 0; i < text.Length; i++)
        {
            char c = text[i];
            if (invalids.Contains(c))
            {
                changed = true;
                char repl = replacement ?? '\0';
                if (fancyReplacements)
                {
                    if (c == '"') repl = '"'; // U+201D right double quotation mark
                    else if (c == '\'') repl = '’'; // U+2019 right single quotation mark
                    else if (c == '/') repl = '⁄'; // U+2044 fraction slash
                }
                if (repl != '\0')
                    sb.Append(repl);
            }
            else
                sb.Append(c);
        }

        if (sb.Length == 0)
            return "_";

        return changed ? sb.ToString() : text;
    }


    /// <summary>
    /// Returns TRUE if the specified path is a valid, local filesystem path.
    /// </summary>
    /// <param name="pathString"></param>
    /// <returns></returns>
    public static bool IsValidLocalPath(this string pathString)
    {
        // From solution at https://stackoverflow.com/a/11636052/949129
        Uri pathUri;
        Boolean isValidUri = Uri.TryCreate(pathString, UriKind.Absolute, out pathUri);
        return isValidUri && pathUri != null && pathUri.IsLoopback;
    }
}
2

Кажется, что это O (n) и не тратит слишком много памяти на строки:

    private static readonly HashSet<char> invalidFileNameChars = new HashSet<char>(Path.GetInvalidFileNameChars());

    public static string RemoveInvalidFileNameChars(string name)
    {
        if (!name.Any(c => invalidFileNameChars.Contains(c))) {
            return name;
        }

        return new string(name.Where(c => !invalidFileNameChars.Contains(c)).ToArray());
    }
  • 1
    Я не думаю, что это O (n), когда вы используете функцию «Any».
  • 0
    @IIARROWS и что это по вашему мнению?
Показать ещё 1 комментарий
1

Имя файла не может содержать символы из символов Path.GetInvalidPathChars(), + и # и других конкретных имен. Мы объединили все проверки в один класс:

public static class FileNameExtensions
{
    private static readonly Lazy<string[]> InvalidFileNameChars =
        new Lazy<string[]>(() => Path.GetInvalidPathChars()
            .Union(Path.GetInvalidFileNameChars()
            .Union(new[] { '+', '#' })).Select(c => c.ToString(CultureInfo.InvariantCulture)).ToArray());


    private static readonly HashSet<string> ProhibitedNames = new HashSet<string>
    {
        @"aux",
        @"con",
        @"clock$",
        @"nul",
        @"prn",

        @"com1",
        @"com2",
        @"com3",
        @"com4",
        @"com5",
        @"com6",
        @"com7",
        @"com8",
        @"com9",

        @"lpt1",
        @"lpt2",
        @"lpt3",
        @"lpt4",
        @"lpt5",
        @"lpt6",
        @"lpt7",
        @"lpt8",
        @"lpt9"
    };

    public static bool IsValidFileName(string fileName)
    {
        return !string.IsNullOrWhiteSpace(fileName)
            && fileName.All(o => !IsInvalidFileNameChar(o))
            && !IsProhibitedName(fileName);
    }

    public static bool IsProhibitedName(string fileName)
    {
        return ProhibitedNames.Contains(fileName.ToLower(CultureInfo.InvariantCulture));
    }

    private static string ReplaceInvalidFileNameSymbols([CanBeNull] this string value, string replacementValue)
    {
        if (value == null)
        {
            return null;
        }

        return InvalidFileNameChars.Value.Aggregate(new StringBuilder(value),
            (sb, currentChar) => sb.Replace(currentChar, replacementValue)).ToString();
    }

    public static bool IsInvalidFileNameChar(char value)
    {
        return InvalidFileNameChars.Value.Contains(value.ToString(CultureInfo.InvariantCulture));
    }

    public static string GetValidFileName([NotNull] this string value)
    {
        return GetValidFileName(value, @"_");
    }

    public static string GetValidFileName([NotNull] this string value, string replacementValue)
    {
        if (string.IsNullOrWhiteSpace(value))
        {
            throw new ArgumentException(@"value should be non empty", nameof(value));
        }

        if (IsProhibitedName(value))
        {
            return (string.IsNullOrWhiteSpace(replacementValue) ? @"_" : replacementValue) + value; 
        }

        return ReplaceInvalidFileNameSymbols(value, replacementValue);
    }

    public static string GetFileNameError(string fileName)
    {
        if (string.IsNullOrWhiteSpace(fileName))
        {
            return CommonResources.SelectReportNameError;
        }

        if (IsProhibitedName(fileName))
        {
            return CommonResources.FileNameIsProhibited;
        }

        var invalidChars = fileName.Where(IsInvalidFileNameChar).Distinct().ToArray();

        if(invalidChars.Length > 0)
        {
            return string.Format(CultureInfo.CurrentCulture,
                invalidChars.Length == 1 ? CommonResources.InvalidCharacter : CommonResources.InvalidCharacters,
                StringExtensions.JoinQuoted(@",", @"'", invalidChars.Select(c => c.ToString(CultureInfo.CurrentCulture))));
        }

        return string.Empty;
    }
}

Метод GetValidFileName заменяет все неверные данные на _.

1
public static bool IsValidFilename(string testName)
{
    return !new Regex("[" + Regex.Escape(new String(System.IO.Path.GetInvalidFileNameChars())) + "]").IsMatch(testName);
}
0

Один лайнер для очистки строки из любых незаконных символов для имен файлов Windows:

public static string CleanIllegalName(string p_testName) => new Regex(string.Format("[{0}]", Regex.Escape(new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars())))).Replace(p_testName, "");
0

Я создал метод расширения, который объединяет несколько предложений:

  1. Удержание незаконных символов в хэш-наборе
  2. Фильтрация символов ниже ascii 127. Поскольку Path.GetInvalidFileNameChars не включает все недопустимые символы, доступные с помощью ascii-кодов от 0 до 255. См. Здесь и MSDN
  3. Возможность определить заменяющий символ

Источник:

public static class FileNameCorrector
{
    private static HashSet<char> invalid = new HashSet<char>(Path.GetInvalidFileNameChars());

    public static string ToValidFileName(this string name, char replacement = '\0')
    {
        var builder = new StringBuilder();
        foreach (var cur in name)
        {
            if (cur > 31 && cur < 128 && !invalid.Contains(cur))
            {
                builder.Append(cur);
            }
            else if (replacement != '\0')
            {
                builder.Append(replacement);
            }
        }

        return builder.ToString();
    }
}
0

Я думаю, что вопрос уже не полный ответил... Ответы описывают только чистое имя файла ИЛИ путь... не оба. Вот мое решение:

private static string CleanPath(string path)
{
    string regexSearch = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
    Regex r = new Regex(string.Format("[{0}]", Regex.Escape(regexSearch)));
    List<string> split = path.Split('\\').ToList();
    string returnValue = split.Aggregate(string.Empty, (current, s) => current + (r.Replace(s, "") + @"\"));
    returnValue = returnValue.TrimEnd('\\');
    return returnValue;
}
0

Это позволит вам хотеть и избегать столкновений

 static string SanitiseFilename(string key)
    {
        var invalidChars = Path.GetInvalidFileNameChars();
        var sb = new StringBuilder();
        foreach (var c in key)
        {
            var invalidCharIndex = -1;
            for (var i = 0; i < invalidChars.Length; i++)
            {
                if (c == invalidChars[i])
                {
                    invalidCharIndex = i;
                }
            }
            if (invalidCharIndex > -1)
            {
                sb.Append("_").Append(invalidCharIndex);
                continue;
            }

            if (c == '_')
            {
                sb.Append("__");
                continue;
            }

            sb.Append(c);
        }
        return sb.ToString();

    }
-5

Или вы можете просто сделать

[YOUR STRING].Replace('\\', ' ').Replace('/', ' ').Replace('"', ' ').Replace('*', ' ').Replace(':', ' ').Replace('?', ' ').Replace('<', ' ').Replace('>', ' ').Replace('|', ' ').Trim();

Ещё вопросы

Сообщество Overcoder
Наверх
Меню