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




12 Answers

public string GetSafeFilename(string filename)
{

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

}

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

c# relative path

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

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



Вы можете удалить незаконные символы с помощью 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());



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

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




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

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

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




Лучший способ удалить недопустимый символ из пользовательского ввода - это заменить нелегальный символ, используя класс 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">



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

wvd_vegt




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

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



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

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




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

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

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

В списке Path.InvalidFileNameChars имеется 40 недопустимых символов. Был поиск сегодня, и в есть неплохой ориентир, который показывает, что hashset займет чуть более половины времени массива / списка для 40 элементов: https://.com/a/10762995/949129

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

Дополнительный бонусный метод «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://.com/a/11636052/949129
        Uri pathUri;
        Boolean isValidUri = Uri.TryCreate(pathString, UriKind.Absolute, out pathUri);
        return isValidUri && pathUri != null && pathUri.IsLoopback;
    }
}



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



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

 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();

    }



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

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



Related