Controlla se un percorso è valido


110

Mi chiedo solo: sto cercando un modo per convalidare se un determinato percorso è valido. (Nota: non voglio controllare se un file esiste! Voglio solo provare la validità del percorso - Quindi se un file potrebbe eventualmente esistere nella posizione) .

Il problema è che non riesco a trovare nulla nell'API .Net. A causa dei molti formati e posizioni supportati da Windows, preferisco usare qualcosa di nativo di MS.

Poiché la funzione dovrebbe essere in grado di controllare:

  • Percorsi relativi (./)
  • Percorsi assoluti (c: \ tmp)
  • Percorsi UNC (\ some-pc \ c $)
  • Limitazioni NTFS come il percorso completo 1024 caratteri - Se non sbaglio, il superamento del percorso renderà un file inaccessibile per molte funzioni interne di Windows. Rinominarlo con Explorer funziona ancora
  • Percorsi GUID volume: "\? \ Volume {GUID} \ somefile.foo

Qualcuno ha una funzione come questa?


Risposte:


58

Prova Uri.IsWellFormedUriString():

  • La stringa non è correttamente sottoposta a escape.

    http://www.example.com/path???/file name
  • La stringa è un Uri assoluto che rappresenta un file Uri implicito.

    c:\\directory\filename
  • La stringa è un URI assoluto a cui manca una barra prima del percorso.

    file://c:/directory/filename
  • La stringa contiene barre rovesciate senza caratteri di escape anche se vengono trattate come barre in avanti.

    http:\\host/path/file
  • La stringa rappresenta un Uri assoluto gerarchico e non contiene ": //".

    www.example.com/path/file
  • Il parser per Uri.Scheme indica che la stringa originale non era ben formata.

    The example depends on the scheme of the URI.

9
Ciò restituisce falso per @"foo\bar\baz", che è un percorso relativo perfettamente valido ...
Thomas Levesque

5
Thomas: Quale UriKind hai specificato? Puoi usare Absolute, Relative o AbsoluteOrRelative.
Dan Gøran Lunde,

1
Anche con UriKind come Relative o AbsoluteOrRelative non ha funzionato per percorsi relativi come menzionato da Thomas. Ho finito per usare invece la risposta di Patko e funziona per i miei scopi.
JohnnyM

1
Ho scoperto che un percorso come \\ computerName \ Dir Name With Spaces \ fileName genera un'eccezione quando si utilizza IsWellFormedUriString (contrariamente alle mie aspettative iniziali), perché gli spazi non sono codificati correttamente. Ho scoperto che potevo semplicemente usare il costruttore Uri (stringa) come convalida, quindi, non dovendo codificare correttamente la stringa prima della convalida.
quintessenza5

3
Restituisce false su un percorso file perfettamente corretto.
Evgeni Petrov


7
private bool IsValidPath(string path)
{
    Regex driveCheck = new Regex(@"^[a-zA-Z]:\\$");
    if (!driveCheck.IsMatch(path.Substring(0, 3))) return false;
    string strTheseAreInvalidFileNameChars = new string(Path.GetInvalidPathChars());
    strTheseAreInvalidFileNameChars += @":/?*" + "\"";
    Regex containsABadCharacter = new Regex("[" + Regex.Escape(strTheseAreInvalidFileNameChars) + "]");
    if (containsABadCharacter.IsMatch(path.Substring(3, path.Length - 3)))
        return false;

    DirectoryInfo dir = new DirectoryInfo(Path.GetFullPath(path));
    if (!dir.Exists)
        dir.Create();
    return true;
}

7

Non ho avuto problemi con il codice seguente. (I percorsi relativi devono iniziare con "/" o "\").

private bool IsValidPath(string path, bool allowRelativePaths = false)
{
    bool isValid = true;

    try
    {
        string fullPath = Path.GetFullPath(path);

        if (allowRelativePaths)
        {
            isValid = Path.IsPathRooted(path);
        }
        else
        {
            string root = Path.GetPathRoot(path);
            isValid = string.IsNullOrEmpty(root.Trim(new char[] { '\\', '/' })) == false;
        }
    }
    catch(Exception ex)
    {
        isValid = false;
    }

    return isValid;
}

Ad esempio, questi restituirebbero false:

IsValidPath("C:/abc*d");
IsValidPath("C:/abc?d");
IsValidPath("C:/abc\"d");
IsValidPath("C:/abc<d");
IsValidPath("C:/abc>d");
IsValidPath("C:/abc|d");
IsValidPath("C:/abc:d");
IsValidPath("");
IsValidPath("./abc");
IsValidPath("./abc", true);
IsValidPath("/abc");
IsValidPath("abc");
IsValidPath("abc", true);

E questi tornerebbero veri:

IsValidPath(@"C:\\abc");
IsValidPath(@"F:\FILES\");
IsValidPath(@"C:\\abc.docx\\defg.docx");
IsValidPath(@"C:/abc/defg");
IsValidPath(@"C:\\\//\/\\/\\\/abc/\/\/\/\///\\\//\defg");
IsValidPath(@"C:/abc/def~`!@#$%^&()_-+={[}];',.g");
IsValidPath(@"C:\\\\\abc////////defg");
IsValidPath(@"/abc", true);
IsValidPath(@"\abc", true);

3

Puoi provare questo codice:

try
{
  Path.GetDirectoryName(myPath);
}
catch
{
  // Path is not valid
}

Non sono sicuro che copra tutti i casi ...


2

La cosa più vicina a cui sono arrivato è provare a crearlo e vedere se riesce.


2

Ci sono molte buone soluzioni qui, ma nessuna di queste controlla se il percorso è radicato in un'unità esistente, eccone un altro:

private bool IsValidPath(string path)
{
    // Check if the path is rooted in a driver
    if (path.Length < 3) return false;
    Regex driveCheck = new Regex(@"^[a-zA-Z]:\\$");
    if (!driveCheck.IsMatch(path.Substring(0, 3))) return false;

    // Check if such driver exists
    IEnumerable<string> allMachineDrivers = DriveInfo.GetDrives().Select(drive => drive.Name);
    if (!allMachineDrivers.Contains(path.Substring(0, 3))) return false;

    // Check if the rest of the path is valid
    string InvalidFileNameChars = new string(Path.GetInvalidPathChars());
    InvalidFileNameChars += @":/?*" + "\"";
    Regex containsABadCharacter = new Regex("[" + Regex.Escape(InvalidFileNameChars) + "]");
    if (containsABadCharacter.IsMatch(path.Substring(3, path.Length - 3)))
        return false;
    if (path[path.Length - 1] == '.') return false;

    return true;
}

Questa soluzione non tiene conto dei percorsi relativi.


1

Ottieni i caratteri non validi da System.IO.Path.GetInvalidPathChars();e controlla se la tua stringa (percorso della directory) li contiene o meno.


3
Questo non è del tutto valido. "C: \ new.folder" è valido mentre "C: \ newfolder". non è. '' è un carattere valido per percorsi / nomi di file, ma non alla fine dell'uri.
claudekennilol

0

4
"[...] non voglio controllare se un file esiste!"
Stefan

3
Quel test per la directory esistente, non perché sia ​​un percorso valido (dove uno potrebbe esistere, o essere creato, dati i privilegi appropriati)
Martijn

3
@ Jason - Non controlla il file, solo la cartella contenente.
Markpsmith

8
ma un percorso di directory valido potrebbe ancora non esistere.
Stefan

-2
private bool IsValidPath(string path)
{
    Regex driveCheck = new Regex(@"^[a-zA-Z]:\\$");

    if (string.IsNullOrWhiteSpace(path) || path.Length < 3)
    {
        return false;
    }

    if (!driveCheck.IsMatch(path.Substring(0, 3)))
    {
        return false;
    }

    var x1 = (path.Substring(3, path.Length - 3));
    string strTheseAreInvalidFileNameChars = new string(Path.GetInvalidPathChars());
    strTheseAreInvalidFileNameChars += @":?*";
    Regex containsABadCharacter = new Regex("[" + Regex.Escape(strTheseAreInvalidFileNameChars) + "]");

    if (containsABadCharacter.IsMatch(path.Substring(3, path.Length - 3)))
    {
        return false;
    }

    var driveLetterWithColonAndSlash = Path.GetPathRoot(path);

    if (!DriveInfo.GetDrives().Any(x => x.Name == driveLetterWithColonAndSlash))
    {
        return false;
    }

    return true;
}

1
qual è lo scopo di x1?
JayJay,

-3

Basta semplicemente usare

if (System.IO.Directory.Exists(path))
{
    ...
}

-4

Potresti provare a utilizzare Path.IsPathRooted () in combinazione con Path.GetInvalidFileNameChars () per assicurarti che il percorso sia a metà strada.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.