Tam yol verilip verilmediğini kontrol edin


105

Verilen yolun tam yol olup olmadığını kontrol etmenin bir yöntemi var mı? Şu anda bunu yapıyorum:

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

Ama bunu kontrol etmenin daha zarif bir yolu olmalı?

Yanıtlar:


142

Kullanmayı dene System.IO.Path.IsPathRooted? Ayrıca truemutlak yollar için geri döner .

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
İkinci örnek nasıl olur da mutlak yol olur?
om471987

4
İkinci yol mutlak değildir, ancak köklüdür. Baştaki eğik çizgi sistemin kökünü gösterir.
detaylor

3
@SmirkinGherkin öyleyse köklü ve mutlak bir yol arasındaki fark nedir?
Jason Axelson 13

1
Dosya sistemine erişimden kaçınma veya geçersiz girdi için istisnalar atma avantajlarını korurken tam bir yol sağlayan bir alternatif için cevabıma bakın ( stackoverflow.com/a/35046453/704808 ) IsPathRooted.
weir

1
@daniel, IIRC, yolun kullanılacak geçerli bir yol olması gerekmediğini göstermek için dahil edildi IsPathRooted, kesinlikle önemli bir şey değildi. Değerlendirilen GetFullPathyolun görülebilmesi için satır dahil edildi
detay

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

Yukarıdaki koşul:

  • dosya sistemi izinleri gerektirmez
  • falsebiçiminin pathgeçersiz olduğu çoğu durumda döndürür (bir istisna atmak yerine)
  • trueyalnızca pathbirimi içeriyorsa döner

OP'nin ortaya koyduğu senaryo gibi senaryolarda, bu nedenle önceki cevaplardaki koşullardan daha uygun olabilir. Yukarıdaki koşulun aksine:

  • path == System.IO.Path.GetFullPath(path)falseşu senaryolarda geri dönmek yerine istisnalar atar :
    • Arayanın gerekli izinleri yok
    • Sistem mutlak yolu alamadı
    • yol, hacim tanımlayıcısının parçası olmayan iki nokta üst üste (":") içeriyor
    • Belirtilen yol, dosya adı veya her ikisi de sistem tarafından tanımlanan maksimum uzunluğu aşıyor
  • System.IO.Path.IsPathRooted(path)döner trueeğer pathtek dizin ayırıcı ile başlar.

Son olarak, yukarıdaki koşulu tamamlayan ve ayrıca kalan olası istisnaları da ortadan kaldıran bir yöntem:

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

DÜZENLEME: em0 iyi yorumunu ve yapılan alternatif cevap gibi yolların meraklı davayı ele C:ve C:dir. Bu tür yolları nasıl idare etmek isteyebileceğinize karar vermenize yardımcı olması için MSDN -> Windows masaüstü uygulamaları -> Geliştirme -> Masaüstü teknolojileri -> Veri Erişimi ve Depolama -> Yerel Dosya Sistemleri - derinlemesine dalmak isteyebilirsiniz. -> Dosya Yönetimi -> Dosya Yönetimi Hakkında -> Dosyaları Oluşturma, Silme ve Saklama -> Dosyaları, Yolları ve Ad Alanlarını Adlandırma -> Tam Nitelikli ve Göreli Yollar

Dosyaları işleyen Windows API işlevleri için, dosya adları genellikle geçerli dizine göre olabilirken, bazı API'ler tam nitelikli bir yol gerektirir. Bir dosya adı, aşağıdakilerden biriyle başlamıyorsa, geçerli dizine göredir:

  • Her zaman iki ters eğik çizgi karakteriyle ("\") başlayan herhangi bir biçimdeki UNC adı. Daha fazla bilgi için sonraki bölüme bakın.
  • Ters eğik çizgiye sahip bir disk göstergesi, örneğin "C: \" veya "d: \".
  • Tek bir ters eğik çizgi, örneğin, "\ dizin" veya "\ dosya.txt". Bu aynı zamanda mutlak yol olarak da adlandırılır.

Bir dosya adı yalnızca bir disk göstergesiyle başlıyorsa, ancak iki nokta üst üste işaretinden sonra ters eğik çizgi ile başlamıyorsa, belirtilen harfe sahip sürücüdeki geçerli dizine göreceli bir yol olarak yorumlanır. Geçerli dizinin, o diskteki en son "dizini değiştir" işlemi sırasında neye ayarlandığına bağlı olarak kök dizin olabilir veya olmayabilir. Bu formatın örnekleri aşağıdaki gibidir:

  • "C: tmp.txt", C sürücüsündeki geçerli dizinde bulunan "tmp.txt" adlı bir dosyayı ifade eder.
  • "C: tempdir \ tmp.txt", C sürücüsündeki geçerli dizine bir alt dizindeki bir dosyayı ifade eder.

[...]


3
Bunun geçersiz yollar için atılmamasını seviyorum, ancak GetFullPath tarafından geçerli dizini kullanarak çözümlenen (yani mutlak değiller) "C:" ve "C: dir" gibi yollar için true döndürüyor. Bunlar için yanlış döndüren bir yanıt yayınladı.
EM0

@ EM0 - Teşekkürler! Az önce bana bir şey öğrettin. :)
weir

15

Deneyin

System.IO.Path.IsPathRooted(template)

Yerel yolların yanı sıra UNC yolları için de çalışır.

Örneğin

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

13

Eski soru, ancak geçerli bir cevap daha. Birimin yerel bir yola dahil edilmesini sağlamanız gerekiyorsa, System.IO.Path.GetFullPath () yöntemini şu şekilde kullanabilirsiniz:

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
İhtiyacım olan buydu ve orijinal soruya daha yakın görünüyor çünkü IsPathRooted 'göreceli yollar için doğru (mutlak yollar olması gerekmez)
bitcoder

GetFullPathdosya sistemine erişir ve bir dizi olası istisna atabilir. Hâlâ tam bir yol sağlayan bir alternatif için cevabıma ( stackoverflow.com/a/35046453/704808 ) bakın .
savak

11

Savağın cevabına dayanarak : bu geçersiz yollar için değil, aynı zamanda false"C:", "C: dirname" ve "\ yol" gibi yollar için de geri döner .

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
}

Bunun Windows ve Linux'ta farklı sonuçlar döndürdüğünü unutmayın, örneğin "/ yol" Linux'ta mutlaktır, ancak Windows'ta değildir.

Ünite testi:

[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);
    }
}

İyi şeyler. Ben fark ettiniz msdn.microsoft.com/en-us/library/windows/desktop/... Windows'ta bir yol olduğunu belirten değil o başlıyorsa göreceli Tek ters eğik çizgi', '\ dizin' veya "\ dosya örneğin, .Txt". Buna mutlak yol da deniyor. '
weir

1
İyi bir nokta! Görünüşe göre terminolojim yanlıştı. "Mutlak yol" dediğimde, MS'in "tam yol" dediği şeyi gerçekten düşünüyordum. İsmi değiştirdim ve bunun için bir test durumu ekledim.
EM0

1
Bu cevap için teşekkürler, bana çok yardımcı oldu. Ancak, \\ server \ gibi bir UNC yolu için yöntemin true döndürdüğünü unutmayın, ancak daha sonra Directory.Exists (yol) (System.ArgumentException öğesini çağırırsanız bu bir istisna atacaktır: 'UNC yolu şu biçimde olmalıdır: \\ sunucu \ paylaşım. ')
Carl

2
İnsanların hala bunu kullandığını ve yeni uç vakalar bulduğunu görmek güzel @Carl Kodu güncelledi ve bunun için test et!
EM0

7

Bir yolun tam nitelikli olup olmadığını kontrol etmek için (MSDN) :

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

Halihazırda önerilenden biraz daha basittir ve sürücüye bağlı yollar için hala yanlış döndürür C:foo. Mantığı doğrudan MSDN'nin "tam nitelikli" tanımına dayanıyor ve yanlış davrandığı herhangi bir örnek bulamadım.


Bununla birlikte, ilginç bir şekilde, .NET Core 2.1'in Path.IsPathFullyQualifieddahili bir yöntem kullanan yeni bir yöntemi var gibi görünüyor PathInternal.IsPartiallyQualified(bağlantı konumu 2018-04-17 itibariyle doğru).

Gelecek nesiller ve bu yazının daha iyi bir şekilde kendini kapsaması için, işte ikincisinin referans olarak uygulanması:

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

Kullandığım çözüm bu

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

Şu şekilde çalışır:

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

Çok ilginç! Kırılgan, örneğin, eğik çizgi tipleriyle eşleşmelidir, ancak bu umut verici.
Nicholas Petersen

Aşağıdaki yollar için yanlış sonuçlar döndürüyor: C:\foo\..\fooveyaC:\foo\.\.\.
sergtk

1

Aşağıdaki işlevi çağırın:

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

MSDN belgesi : Path.IsPathFullyQualified Yöntemi

MSDN belgesindeki yararlı alıntı aşağıdaki gibidir:

Bu yöntem, alternatif dizin ayırıcısını kullanan yolları işler. Köklü yolların ( IsPathRooted (String) ) göreceli olmadığını varsaymak sık sık yapılan bir hatadır . Örneğin, "C: a" sürücüye bağlıdır, yani C: için geçerli dizine göre çözümlenir (köklü, ancak göreli). "C: \ a" köklüdür ve göreceli değildir, yani geçerli dizin yolu değiştirmek için kullanılmaz.


0

Tam yol derken neyi kastettiğinizden tam olarak emin değilim (örnekte kökten itibaren alakasız demek istediğiniz varsayılırsa), fiziksel dosya sistemi yollarıyla çalışırken size yardımcı olması için Path sınıfını kullanabilirsiniz. çoğu olasılık için sen.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.