Безопасное/Разрешенное имя файла для .NET.
Есть ли какой-либо стандартизованный/лирированный/проверенный способ в .NET, чтобы взять произвольную строку и калечить ее таким образом, чтобы она представляла допустимое имя файла?
Перемещение моей собственной функции char -replace достаточно просто, но я бы хотел, чтобы что-то было немного более надежным и возобновленным.
Ответы
Ответ 1
Эта проблема не так проста, как вы думаете. Мало того, что символы в Path.GetInvalidFileNameChars
являются незаконными, существует несколько имен файлов, таких как "PRN" и "CON", которые зарезервированы для Windows и не могут быть созданы. Любое имя, которое заканчивается на. также является незаконным в Windows. Кроме того, существуют различные ограничения длины. Прочитайте полный список здесь.
Если этого недостаточно, разные файловые системы имеют разные ограничения, например, имена файлов ISO 9660 не могут начинаться с "-", но могут содержать его.
Ответ 2
Вы можете использовать Path.GetInvalidFileNameChars, чтобы проверить, какие символы строки являются недопустимыми, и либо преобразовать их в действительный char такой в качестве дефиса или (если вам требуется двунаправленное преобразование) заменить их маркером перехода, таким как %
, последовать шестнадцатеричному представлению своих кодов Юникода (я действительно использовал этот метод один раз, но не имею кода справа в настоящее время).
EDIT: на всякий случай кто-то заинтересован, вот код.
/// <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("%!", "%");
}
Ответ 3
Можете ли вы предоставить более подробную информацию о том, что вы подразумеваете под "сгенерировать из произвольной строки"? Основываясь на том, что вы говорите, похоже, вы спрашиваете
Есть ли способ взять произвольную строку и калечить ее таким образом, чтобы она представляла допустимое имя файла?
Если в этом случае нет никакой стандартной функции, о которой я знаю. Однако вы можете использовать следующее, которое должно сделать трюк
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();
}
Ответ 4
Есть ли у вас взгляд на Path.GetInvalidFileNameChars?
Найдено в Действительно полезные .NET-классы Часть 1 - System.IO.Path
Ответ 5
Просто для удовольствия, я сделал это в одной строке.
Regex.Replace("http://codereview.stackexchange.com/info/33851/how-can-i-improve-my-code/33857#33857", "[" + string.Join("", Path.GetInvalidFileNameChars().Select (p => p.ToString())) + "]", "_")