Frage Gibt es eine Möglichkeit, Zeichenketten in c # sicher zu machen?


Mein Programm wird beliebige Strings aus dem Internet übernehmen und für Dateinamen verwenden. Gibt es eine einfache Möglichkeit, die fehlerhaften Zeichen aus diesen Zeichenfolgen zu entfernen, oder muss ich dafür eine benutzerdefinierte Funktion schreiben?


75
2017-12-02 06:00


Ursprung


Antworten:


Ugh, ich hasse es, wenn Leute raten, welche Charaktere gültig sind. Abgesehen davon, dass sie komplett nicht portierbar waren (sie dachten immer an Mono), versäumten beide früheren Kommentare mehr als 25 ungültige Zeichen.

'Clean just a filename
Dim filename As String = "salmnas dlajhdla kjha;dmas'lkasn"
For Each c In IO.Path.GetInvalidFileNameChars
    filename = filename.Replace(c, "")
Next

'See also IO.Path.GetInvalidPathChars

154
2017-12-02 07:35



Diese Frage wurde gestellt viele  mal  Vor und, wie schon oft erwähnt, IO.Path.GetInvalidFileNameChars ist nicht ausreichend.

Erstens gibt es viele Namen wie PRN und CON, die reserviert und für Dateinamen nicht erlaubt sind. Es gibt andere Namen, die nur im Stammordner erlaubt sind. Namen, die in einem Zeitraum enden, sind ebenfalls nicht zulässig.

Zweitens gibt es eine Vielzahl von Längenbeschränkungen. Lesen Sie die vollständige Liste für NTFS Hier.

Drittens können Sie Dateisysteme anhängen, die andere Einschränkungen haben. Zum Beispiel können ISO 9660-Dateinamen nicht mit "-" beginnen, sondern können sie enthalten.

Viertens, was tun Sie, wenn zwei Prozesse "willkürlich" den gleichen Namen wählen?

Im Allgemeinen ist die Verwendung von extern generierten Namen für Dateinamen eine schlechte Idee. Ich schlage vor, eigene private Dateinamen zu generieren und intern lesbare Namen intern zu speichern.


30
2017-09-09 16:24



So entfernen Sie ungültige Zeichen:

static readonly char[] invalidFileNameChars = Path.GetInvalidFileNameChars();

// Builds a string out of valid chars
var validFilename = new string(filename.Where(ch => !invalidFileNameChars.Contains(ch)).ToArray());

So ersetzen Sie ungültige Zeichen:

static readonly char[] invalidFileNameChars = Path.GetInvalidFileNameChars();

// Builds a string out of valid chars and an _ for invalid ones
var validFilename = new string(filename.Select(ch => invalidFileNameChars.Contains(ch) ? '_' : ch).ToArray());

Um ungültige Zeichen zu ersetzen (und möglichen Namenskonflikt wie Hell * vs Hell $ zu vermeiden):

static readonly IList<char> invalidFileNameChars = Path.GetInvalidFileNameChars();

// Builds a string out of valid chars and replaces invalid chars with a unique letter (Moves the Char into the letter range of unicode, starting at "A")
var validFilename = new string(filename.Select(ch => invalidFileNameChars.Contains(ch) ? Convert.ToChar(invalidFileNameChars.IndexOf(ch) + 65) : ch).ToArray());

21
2017-09-09 15:58



Ich stimme mit Grauenwolf überein und kann es sehr empfehlen Path.GetInvalidFileNameChars()

Hier ist mein C # Beitrag:

string file = @"38?/.\}[+=n a882 a.a*/|n^%$ ad#(-))";
Array.ForEach(Path.GetInvalidFileNameChars(), 
      c => file = file.Replace(c.ToString(), String.Empty));

p.s. - Das ist kryptischer als es sein sollte - ich habe versucht, knapp zu sein.


19
2017-12-02 08:03



Hier ist meine Version:

static string GetSafeFileName(string name, char replace = '_') {
  char[] invalids = Path.GetInvalidFileNameChars();
  return new string(name.Select(c => invalids.Contains(c) ? replace : c).ToArray());
}

Ich bin nicht sicher, wie das Ergebnis von GetInvalidFileNameChars berechnet wird, aber das "Get" schlägt vor, dass es nicht-trivial ist, also cache ich die Ergebnisse. Darüber hinaus wird die Eingabezeichenfolge nur einmal statt mehrmals durchlaufen, wie bei den obigen Lösungen, die über die Menge ungültiger Zeichen iterieren und sie einzeln in der Quellzeichenfolge ersetzen. Außerdem mag ich die Where-basierten Lösungen, aber ich ersetze lieber ungültige Zeichen, anstatt sie zu entfernen. Schließlich ist meine Ersetzung genau ein Zeichen, um die Umwandlung von Zeichen in Zeichenfolgen zu vermeiden, wenn ich über die Zeichenfolge iteriere.

Ich sage das alles ohne Profiling - das hat mich einfach "gut" gefühlt. :)


11
2017-09-20 12:59



Hier ist die Funktion, die ich jetzt benutze (danke jcollum für das C # -Beispiel):

public static string MakeSafeFilename(string filename, char replaceChar)
{
    foreach (char c in System.IO.Path.GetInvalidFileNameChars())
    {
        filename = filename.Replace(c, replaceChar);
    }
    return filename;
}

Ich füge das einfach in eine "Helfer" -Klasse ein.


10
2018-05-28 02:42



Wenn Sie schnell alle Sonderzeichen entfernen möchten, die manchmal für Dateinamen besser lesbar sind, funktioniert das gut:

string myCrazyName = "q`w^e!r@t#y$u%i^o&p*a(s)d_f-g+h=j{k}l|z:x\"c<v>b?n[m]q\\w;e'r,t.y/u";
string safeName = Regex.Replace(
    myCrazyName,
    "\W",  /*Matches any nonword character. Equivalent to '[^A-Za-z0-9_]'*/
    "",
    RegexOptions.IgnoreCase);
// safeName == "qwertyuiopasd_fghjklzxcvbnmqwertyu"

6
2018-04-18 12:30



static class Utils
{
    public static string MakeFileSystemSafe(this string s)
    {
        return new string(s.Where(IsFileSystemSafe).ToArray());
    }

    public static bool IsFileSystemSafe(char c)
    {
        return !Path.GetInvalidFileNameChars().Contains(c);
    }
}

5
2017-07-12 19:55



Hier ist, was ich gerade zu ClipFlair hinzugefügt habe (http://clipflair.codeplex.com) StringExtensions statische Klasse (Utils.Silverlight-Projekt), basierend auf Informationen, die von den Links zu verwandten stackoverflow-Fragen gesammelt wurden, die von Dour High Arch oben gepostet wurden:

public static string ReplaceInvalidFileNameChars(this string s, string replacement = "")
{
  return Regex.Replace(s,
    "[" + Regex.Escape(new String(System.IO.Path.GetInvalidPathChars())) + "]",
    replacement, //can even use a replacement string of any length
    RegexOptions.IgnoreCase);
    //not using System.IO.Path.InvalidPathChars (deprecated insecure API)
}

4
2018-04-28 02:47



Warum konvertieren Sie die Zeichenfolge nicht in ein Base64-Äquivalent wie folgt:

string UnsafeFileName = "salmnas dlajhdla kjha;dmas'lkasn";
string SafeFileName = Convert.ToBase64String(Encoding.UTF8.GetBytes(UnsafeFileName));

Wenn Sie es zurück konvertieren möchten, können Sie es lesen:

UnsafeFileName = Encoding.UTF8.GetString(Convert.FromBase64String(SafeFileName));

Ich habe dies verwendet, um PNG-Dateien mit einem eindeutigen Namen aus einer zufälligen Beschreibung zu speichern.


3
2018-02-19 18:22