Безопасный / Разрешенный очиститель имени файла для .NET - PullRequest
6 голосов
/ 08 декабря 2009

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

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

Ответы [ 5 ]

14 голосов
/ 08 декабря 2009

Вы можете использовать Path.GetInvalidFileNameChars , чтобы проверить, какие символы строки недопустимы, и либо преобразовать их в действительный символ, такой как дефис, либо (если вам нужно двунаправленное преобразование) заменить их на escape-токен, такой как %, следовал за шестнадцатеричным представлением их кодов Unicode (я фактически использовал эту технику однажды, но сейчас у меня нет кода).

РЕДАКТИРОВАТЬ : На случай, если кому-то интересно, вот код.

/// <summary>
/// Escapes an object name so that it is a valid filename.
/// </summary>
/// <param name="fileName">Original object name.</param>
/// <returns>Escaped name.</returns>
/// <remarks>
/// All characters that are not valid for a filename, plus "%" and ".", are converted into "%uuuu", where uuuu is the hexadecimal
/// unicode representation of the character.
/// </remarks>
private string EscapeFilename(string fileName)
{
    char[] invalidChars=Path.GetInvalidFileNameChars();

    // Replace "%", then replace all other characters, then replace "."

    fileName=fileName.Replace("%", "%0025");
    foreach(char invalidChar in invalidChars)
    {
        fileName=fileName.Replace(invalidChar.ToString(), string.Format("%{0,4:X}", Convert.ToInt16(invalidChar)).Replace(' ', '0'));
    }
    return fileName.Replace(".", "%002E");
}

/// <summary>
/// Unescapes an escaped file name so that the original object name is obtained.
/// </summary>
/// <param name="escapedName">Escaped object name (see the EscapeFilename method).</param>
/// <returns>Unescaped (original) object name.</returns>
public string UnescapeFilename(string escapedName)
{
    //We need to temporarily replace %0025 with %! to prevent a name
    //originally containing escaped sequences to be unescaped incorrectly
    //(for example: ".%002E" once escaped is "%002E%0025002E".
    //If we don't do this temporary replace, it would be unescaped to "..")

    string unescapedName=escapedName.Replace("%0025", "%!");
    Regex regex=new Regex("%(?<esc>[0-9A-Fa-f]{4})");
    Match m=regex.Match(escapedName);
    while(m.Success)
    {
        foreach(Capture cap in m.Groups["esc"].Captures)
            unescapedName=unescapedName.Replace("%"+cap.Value, Convert.ToChar(int.Parse(cap.Value, NumberStyles.HexNumber)).ToString());
        m=m.NextMatch();
    }
    return unescapedName.Replace("%!", "%");
}
9 голосов
/ 08 декабря 2009

Эта проблема не так проста, как вы думаете. Мало того, что символы в Path.GetInvalidFileNameChars недопустимы, есть несколько имен файлов, таких как «PRN» и «CON», которые зарезервированы Windows и не могут быть созданы. Любое имя, которое заканчивается на "." также незаконно в Windows. Кроме того, существуют различные ограничения по длине. Читайте полный список здесь .

Если этого недостаточно, разные файловые системы имеют разные ограничения, например, имена файлов ISO 9660 не могут начинаться с "-", но могут содержать его.

2 голосов
/ 08 декабря 2009

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

Есть ли способ взять произвольную строку и исказить ее так, чтобы она представляла правильное имя файла?

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

public static string MakeValidFileName(string name) {
  var invalid = Path.GetInvalidFileNameChars();
  var builder = new StringBuilder();
  foreach ( var cur in name ) {
    builder.Append(invalid.Contains(cur) ? '_' : cur);
  }
  return builder.ToString();
}
1 голос
/ 08 декабря 2009

Вы смотрели на Path.GetInvalidFileNameChars?

Найдено в Действительно полезные .NET классы, часть 1 - System.IO.Path

0 голосов
/ 05 ноября 2013

Просто для удовольствия, я сделал это в одну строку ..

Regex.Replace("http://codereview.stackexchange.com/questions/33851/how-can-i-improve-my-code/33857#33857", "[" + string.Join("", Path.GetInvalidFileNameChars().Select (p => p.ToString())) + "]", "_")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...