Verificare se è stato fornito il percorso completo


104

Esiste un metodo per verificare se il percorso specificato è completo? In questo momento sto facendo questo:

if (template.Contains(":\\")) //full path already given
{
}
else //calculate the path from local assembly
{
}

Ma ci deve essere un modo più elegante per verificarlo?

Risposte:


141

Prova a usare System.IO.Path.IsPathRooted? Ritorna anche trueper percorsi assoluti.

System.IO.Path.IsPathRooted(@"c:\foo"); // true
System.IO.Path.IsPathRooted(@"\foo"); // true
System.IO.Path.IsPathRooted("foo"); // false

System.IO.Path.IsPathRooted(@"c:1\foo"); // surprisingly also true
System.IO.Path.GetFullPath(@"c:1\foo");// returns "[current working directory]\1\foo"

14
Come mai il secondo esempio è il percorso assoluto?
om471987

4
Il secondo percorso non è assoluto, tuttavia è radicato. La barra iniziale indica la radice del sistema.
detaylor

3
@SmirkinGherkin quindi qual è la differenza tra un percorso radicato e un percorso assoluto?
Jason Axelson

1
Vedere la mia risposta ( stackoverflow.com/a/35046453/704808 ) per un'alternativa che garantisce un percorso completo pur mantenendo i vantaggi di IsPathRooted: evitare l'accesso al file system o generare eccezioni per input non valido.
sbarramento

1
@daniel, IIRC è stato incluso per dimostrare che il percorso non doveva essere un percorso valido per essere utilizzato IsPathRooted, di certo non era niente di significativo. La GetFullPathlinea è stata inclusa in modo che il percorso in corso di valutazione potesse essere osservato
detaylor

30
Path.IsPathRooted(path)
&& !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)

La condizione di cui sopra:

  • non richiede autorizzazioni di file system
  • restituisce falsenella maggior parte dei casi in cui il formato dipath non è valido (anziché generare un'eccezione)
  • restituisce truesolo se pathinclude il volume

In scenari come quello proposto dal PO, potrebbe quindi essere più adatto rispetto alle condizioni delle risposte precedenti. A differenza della condizione di cui sopra:

  • path == System.IO.Path.GetFullPath(path)genera eccezioni anziché restituire falsein questi scenari:
    • Il chiamante non dispone delle autorizzazioni richieste
    • Il sistema non è riuscito a recuperare il percorso assoluto
    • percorso contiene due punti (":") che non fa parte di un identificatore di volume
    • Il percorso, il nome file o entrambi specificati superano la lunghezza massima definita dal sistema
  • System.IO.Path.IsPathRooted(path)restituisce truese pathinizia con un singolo separatore di directory.

Infine, ecco un metodo che avvolge la condizione di cui sopra e preclude anche le restanti possibili eccezioni:

public static bool IsFullPath(string path) {
    return !String.IsNullOrWhiteSpace(path)
        && path.IndexOfAny(System.IO.Path.GetInvalidPathChars().ToArray()) == -1
        && Path.IsPathRooted(path)
        && !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal);
}

EDIT: EM0 ha fatto un buon commento e una risposta alternativa affrontando il curioso caso di percorsi come C:e C:dir. Per decidere come gestire tali percorsi, potresti voler approfondire MSDN -> Applicazioni desktop Windows -> Sviluppo -> Tecnologie desktop -> Accesso e archiviazione dati -> File system locali - -> Gestione file -> Informazioni sulla gestione dei file -> Creazione, eliminazione e manutenzione dei file -> Denominazione di file, percorsi e spazi dei nomi -> Percorsi completamente qualificati e relativi

Per le funzioni API di Windows che manipolano i file, i nomi dei file possono spesso essere relativi alla directory corrente, mentre alcune API richiedono un percorso completo. Un nome file è relativo alla directory corrente se non inizia con uno dei seguenti:

  • Un nome UNC di qualsiasi formato, che inizia sempre con due caratteri barra rovesciata ("\"). Per ulteriori informazioni, vedere la sezione successiva.
  • Un designatore di disco con una barra rovesciata, ad esempio "C: \" o "d: \".
  • Una singola barra rovesciata, ad esempio "\ directory" o "\ file.txt". Viene anche definito percorso assoluto.

Se un nome file inizia solo con un designatore di disco ma non con la barra rovesciata dopo i due punti, viene interpretato come un percorso relativo alla directory corrente sull'unità con la lettera specificata. Notare che la directory corrente può essere o meno la directory root a seconda di cosa è stata impostata durante l'operazione di "modifica directory" più recente su quel disco. Esempi di questo formato sono i seguenti:

  • "C: tmp.txt" fa riferimento a un file denominato "tmp.txt" nella directory corrente sull'unità C.
  • "C: tempdir \ tmp.txt" fa riferimento a un file in una sottodirectory nella directory corrente sull'unità C.

[...]


3
Mi piace che questo non generi percorsi non validi, ma restituisce true per percorsi come "C:" e "C: dir", che vengono risolti da GetFullPath utilizzando la directory corrente (quindi non sono assoluti). Inserita una risposta che restituisce falso per questi.
EM0

@ EM0 - Grazie! Mi hai appena insegnato qualcosa. :)
sbarramento

15

Provare

System.IO.Path.IsPathRooted(template)

Funziona per percorsi UNC e locali.

Per esempio

Path.IsPathRooted(@"\\MyServer\MyShare\MyDirectory")  // returns true
Path.IsPathRooted(@"C:\\MyDirectory")  // returns true

13

Vecchia domanda, ma un'altra risposta applicabile. Se è necessario assicurarsi che il volume sia incluso in un percorso locale, è possibile utilizzare System.IO.Path.GetFullPath () in questo modo:

if (template == System.IO.Path.GetFullPath(template))
{
    ; //template is full path including volume or full UNC path
}
else
{
    if (useCurrentPathAndVolume)
        template = System.IO.Path.GetFullPath(template);
    else
        template = Assembly.GetExecutingAssembly().Location
}

3
Questo era ciò di cui avevo bisogno e sembra più vicino alla domanda originale poiché IsPathRooted 'restituisce true per percorsi relativi (non necessariamente percorsi assoluti)
bitcoder

GetFullPathaccede al file system e può generare una serie di possibili eccezioni. Vedi la mia risposta ( stackoverflow.com/a/35046453/704808 ) per un'alternativa che garantisce comunque un percorso completo.
sbarramento

11

Basandosi sulla risposta di weir : questo non genera percorsi non validi, ma restituisce anche falsepercorsi come "C:", "C: dirname" e "\ path".

public static bool IsFullPath(string path)
{
    if (string.IsNullOrWhiteSpace(path) || path.IndexOfAny(Path.GetInvalidPathChars()) != -1 || !Path.IsPathRooted(path))
        return false;

    string pathRoot = Path.GetPathRoot(path);
    if (pathRoot.Length <= 2 && pathRoot != "/") // Accepts X:\ and \\UNC\PATH, rejects empty string, \ and X:, but accepts / to support Linux
        return false;

    if (pathRoot[0] != '\\' || pathRoot[1] != '\\')
        return true; // Rooted and not a UNC path

    return pathRoot.Trim('\\').IndexOf('\\') != -1; // A UNC server name without a share name (e.g "\\NAME" or "\\NAME\") is invalid
}

Notare che questo restituisce risultati diversi su Windows e Linux, ad esempio "/ path" è assoluto su Linux, ma non su Windows.

Test unitario:

[Test]
public void IsFullPath()
{
    bool isWindows = Environment.OSVersion.Platform.ToString().StartsWith("Win"); // .NET Framework
    // bool isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows); // .NET Core

    // These are full paths on Windows, but not on Linux
    TryIsFullPath(@"C:\dir\file.ext", isWindows);
    TryIsFullPath(@"C:\dir\", isWindows);
    TryIsFullPath(@"C:\dir", isWindows);
    TryIsFullPath(@"C:\", isWindows);
    TryIsFullPath(@"\\unc\share\dir\file.ext", isWindows);
    TryIsFullPath(@"\\unc\share", isWindows);

    // These are full paths on Linux, but not on Windows
    TryIsFullPath(@"/some/file", !isWindows);
    TryIsFullPath(@"/dir", !isWindows);
    TryIsFullPath(@"/", !isWindows);

    // Not full paths on either Windows or Linux
    TryIsFullPath(@"file.ext", false);
    TryIsFullPath(@"dir\file.ext", false);
    TryIsFullPath(@"\dir\file.ext", false);
    TryIsFullPath(@"C:", false);
    TryIsFullPath(@"C:dir\file.ext", false);
    TryIsFullPath(@"\dir", false); // An "absolute", but not "full" path

    // Invalid on both Windows and Linux
    TryIsFullPath(null, false, false);
    TryIsFullPath("", false, false);
    TryIsFullPath("   ", false, false);
    TryIsFullPath(@"C:\inval|d", false, false);
    TryIsFullPath(@"\\is_this_a_dir_or_a_hostname", false, false);
    TryIsFullPath(@"\\is_this_a_dir_or_a_hostname\", false, !isWindows);
    TryIsFullPath(@"\\is_this_a_dir_or_a_hostname\\", false, !isWindows);
}

private static void TryIsFullPath(string path, bool expectedIsFull, bool expectedIsValid = true)
{
    Assert.AreEqual(expectedIsFull, PathUtils.IsFullPath(path), "IsFullPath('" + path + "')");

    if (expectedIsFull)
    {
        Assert.AreEqual(path, Path.GetFullPath(path));
    }
    else if (expectedIsValid)
    {
        Assert.AreNotEqual(path, Path.GetFullPath(path));
    }
    else
    {
        Assert.That(() => Path.GetFullPath(path), Throws.Exception);
    }
}

Roba buona. Ho notato che msdn.microsoft.com/en-us/library/windows/desktop/… afferma che su Windows un percorso non è relativo se inizia con "Una singola barra rovesciata, ad esempio" \ directory "o" \ file .testo". Questo viene anche definito percorso assoluto. '
sbarramento

1
Buon punto! Sembra che la mia terminologia fosse sbagliata. Quando ho detto "percorso assoluto" stavo davvero pensando a quello che la SM chiama un "percorso completo". Ho cambiato il nome e aggiunto un test case per questo.
EM0

1
Grazie per questa risposta, mi ha aiutato molto. Tuttavia, tieni presente che per un percorso UNC come \\ server \, il metodo restituisce true, ma questo genererà un'eccezione se quindi chiami Directory.Exists (path) (System.ArgumentException: 'Il percorso UNC dovrebbe essere nel formato \\ server \ share. ')
Carl

2
È bello vedere persone che lo usano ancora e che trovano nuovi casi limite @Carl ha aggiornato il codice e testato per quello!
EM0

6

Per verificare se un percorso è completo (MSDN) :

public static bool IsPathFullyQualified(string path)
{
    var root = Path.GetPathRoot(path);
    return root.StartsWith(@"\\") || root.EndsWith(@"\");
}

È un po 'più semplice di quanto è già stato proposto e restituisce ancora false per percorsi relativi all'unità come C:foo. La sua logica si basa direttamente sulla definizione MSDN di "pienamente qualificato" e non ho trovato alcun esempio su cui si comporta male.


È interessante notare che .NET Core 2.1 sembra avere un nuovo metodo Path.IsPathFullyQualifiedche utilizza un metodo interno PathInternal.IsPartiallyQualified(posizione del collegamento accurata al 2017-04-17).

Per i posteri e un migliore autocontenimento di questo post, ecco l'implementazione di quest'ultimo come riferimento:

internal static bool IsPartiallyQualified(ReadOnlySpan<char> path)
{
    if (path.Length < 2)
    {
        // It isn't fixed, it must be relative.  There is no way to specify a fixed
        // path with one character (or less).
        return true;
    }

    if (IsDirectorySeparator(path[0]))
    {
        // There is no valid way to specify a relative path with two initial slashes or
        // \? as ? isn't valid for drive relative paths and \??\ is equivalent to \\?\
        return !(path[1] == '?' || IsDirectorySeparator(path[1]));
    }

    // The only way to specify a fixed path that doesn't begin with two slashes
    // is the drive, colon, slash format- i.e. C:\
    return !((path.Length >= 3)
        && (path[1] == VolumeSeparatorChar)
        && IsDirectorySeparator(path[2])
        // To match old behavior we'll check the drive character for validity as the path is technically
        // not qualified if you don't have a valid drive. "=:\" is the "=" file's default data stream.
        && IsValidDriveChar(path[0]));
}

4

Questa è la soluzione che uso

public static bool IsFullPath(string path)
{
    try
    {
        return Path.GetFullPath(path) == path;
    }
    catch
    {
        return false;
    }
}

Funziona nel modo seguente:

IsFullPath(@"c:\foo"); // true
IsFullPath(@"C:\foo"); // true
IsFullPath(@"c:\foo\"); // true
IsFullPath(@"c:/foo"); // false
IsFullPath(@"\foo"); // false
IsFullPath(@"foo"); // false
IsFullPath(@"c:1\foo\"); // false

Molto interessante! È fragile, ad esempio, deve corrispondere ai tipi di barra, ma questo è promettente.
Nicholas Petersen

Restituisce risultati errati per i seguenti percorsi: C:\foo\..\foooC:\foo\.\.\.
sergtk

1

Chiama la seguente funzione:

Path.IsPathFullyQualified(@"c:\foo")

Documento MSDN: Documento metodo Path.IsPathFullyQualified

Segue l'utile citazione dal documento MSDN:

Questo metodo gestisce i percorsi che utilizzano il separatore di directory alternativo. È un errore frequente presumere che i percorsi radicati ( IsPathRooted (String) ) non siano relativi. Ad esempio, "C: a" è relativo all'unità, ovvero viene risolto rispetto alla directory corrente per C: (radice, ma relativa). "C: \ a" è radicato e non relativo, ovvero la directory corrente non viene utilizzata per modificare il percorso.


0

Non sono proprio sicuro di cosa intendi per percorso completo (anche se dall'esempio intendi non relativo dalla radice in poi), beh, puoi usare la classe Path per aiutarti a lavorare con i percorsi fisici del filesystem, che dovrebbe coprire tu per la maggior parte delle eventualità.

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.