Czy jest jakiś sposób na zabezpieczenie ścieżki pliku w c#?

Mój program pobierze dowolne Ciągi z Internetu i użyje ich do nazw plików. Czy istnieje prosty sposób na usunięcie złych znaków z tych ciągów, czy też muszę napisać do tego niestandardową funkcję?

Author: Martin Doms, 2008-12-02

12 answers

Nie CIERPIĘ, Gdy ludzie próbują zgadywać, które postacie są ważne. Poza tym, że jest całkowicie nie przenośny (zawsze myśląc o Mono), oba wcześniejsze komentarze ominęły więcej 25 nieprawidłowych znaków.

'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
 157
Author: Jonathan Allen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-05 12:07:42

To pytanie zostało zadane Wielu Czasy przed i, jak podkreślano wiele razy wcześniej, {[0] } nie jest odpowiednie.

Po pierwsze, istnieje wiele nazw, takich jak PRN i CON, które są zastrzeżone i niedozwolone dla nazw plików. Istnieją inne nazwy nie dozwolone tylko w folderze głównym. Nazwy, które kończą się kropką, również nie są dozwolone.

Po drugie, istnieją różne ograniczenia długości. Przeczytaj pełną listę NTFS tutaj .

Po trzecie, możesz dołączyć do systemów plików, które mają inne ograniczenia. Na przykład nazwy plików ISO 9660 nie mogą zaczynać się od" -", ale mogą je zawierać.

Po czwarte, co zrobić, jeśli dwa procesy "arbitralnie" wybierają tę samą nazwę?

Ogólnie rzecz biorąc, używanie zewnętrznych nazw dla nazw plików jest złym pomysłem. Sugeruję wygenerowanie własnych prywatnych nazw plików i wewnętrzne przechowywanie nazw czytelnych dla człowieka.

 30
Author: Dour High Arch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:30

Aby usunąć nieprawidłowe znaki:

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

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

Aby zastąpić nieprawidłowe znaki:

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

Aby zastąpić nieprawidłowe znaki (i uniknąć potencjalnego konfliktu nazw jak Hell * vs Hell$):

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());
 25
Author: Squirrel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-26 09:01:00

Zgadzam się z Grauenwolf i Gorąco polecam Path.GetInvalidFileNameChars()

Oto mój wkład w C#:

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

P. s. -- to jest bardziej tajemnicze niż powinno być -- starałem się być zwięzły.

 19
Author: Aaron Wagner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-02 08:03:36

Oto moja wersja:

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

Nie jestem pewien, jak obliczany jest wynik GetInvalidFileNameChars, ale " Get " sugeruje, że jest nietrywialny, więc buforuję wyniki. Co więcej, to tylko przemieszcza łańcuch wejściowy raz, a nie wiele razy, tak jak powyższe rozwiązania iterują nad zestawem nieprawidłowych znaków, zastępując je w łańcuchu źródłowym pojedynczo. Również lubię rozwiązania oparte na Where, ale wolę zastąpić nieprawidłowe znaki zamiast je usuwać. Wreszcie, mój zamiana jest dokładnie jednym znakiem, aby uniknąć konwersji znaków na ciągi znaków, gdy iteruję nad ciągiem.

Mówię, że nie robiąc profilowania, ten po prostu "czuł" się dla mnie miły. : )
 12
Author: csells,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-20 12:59:40

Oto funkcja, której teraz używam (dzięki jcollum za przykład C#):

public static string MakeSafeFilename(string filename, char replaceChar)
{
    foreach (char c in System.IO.Path.GetInvalidFileNameChars())
    {
        filename = filename.Replace(c, replaceChar);
    }
    return filename;
}
Dla wygody umieściłem to w klasie "pomocników".
 10
Author: sidewinderguy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-06 17:47:03

Jeśli chcesz szybko usunąć wszystkie znaki specjalne, które są czasami bardziej czytelne dla użytkownika dla nazw plików, działa to ładnie:

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
Author: Keith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-28 02:42:19
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
Author: Ronnie Overby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-18 12:30:27

Oto co właśnie dodałem do ClipFlair ' s ( http://clipflair.codeplex.com ) StringExtensions static class (Utils.Projekt Silverlight), na podstawie informacji zebranych z linków do powiązanych pytań stoskoverflow zamieszczonych przez Dour High Arch powyżej: {]}

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
Author: George Birbilis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-12 19:55:30

Dlaczego nie przekonwertować łańcucha na odpowiednik Base64 w ten sposób:

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

Jeśli chcesz przekonwertować go z powrotem, abyś mógł go przeczytać:

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

Użyłem tego do zapisania plików PNG o unikalnej nazwie z losowego opisu.

 3
Author: Bart Vanseer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-28 02:47:31
private void textBoxFileName_KeyPress(object sender, KeyPressEventArgs e)
{
   e.Handled = CheckFileNameSafeCharacters(e);
}

/// <summary>
/// This is a good function for making sure that a user who is naming a file uses proper characters
/// </summary>
/// <param name="e"></param>
/// <returns></returns>
internal static bool CheckFileNameSafeCharacters(System.Windows.Forms.KeyPressEventArgs e)
{
    if (e.KeyChar.Equals(24) || 
        e.KeyChar.Equals(3) || 
        e.KeyChar.Equals(22) || 
        e.KeyChar.Equals(26) || 
        e.KeyChar.Equals(25))//Control-X, C, V, Z and Y
            return false;
    if (e.KeyChar.Equals('\b'))//backspace
        return false;

    char[] charArray = Path.GetInvalidFileNameChars();
    if (charArray.Contains(e.KeyChar))
       return true;//Stop the character from being entered into the control since it is non-numerical
    else
        return false;            
}
 2
Author: ecklerpa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-19 18:22:19

Uważam, że użycie tego jest szybkie i łatwe do zrozumienia:

<Extension()>
Public Function MakeSafeFileName(FileName As String) As String
    Return FileName.Where(Function(x) Not IO.Path.GetInvalidFileNameChars.Contains(x)).ToArray
End Function

To działa, ponieważ string jest IEnumerable jako tablica char i istnieje łańcuch konstruktora string, który pobiera tablicę char.

 1
Author: cjbarth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-09 18:28:04