ตรวจสอบว่าเส้นทางถูกต้องหรือไม่


110

ฉันแค่สงสัย: ฉันกำลังมองหาวิธีตรวจสอบว่าเส้นทางนั้นถูกต้องหรือไม่ (หมายเหตุ: ฉันไม่ต้องการที่จะตรวจสอบว่าไฟล์ที่มีอยู่เป็นฉันเพียงต้องการที่จะพิสูจน์ความถูกต้องของเส้นทาง - ดังนั้นถ้าไฟล์ที่อาจจะอยู่ในสถานที่)

ปัญหาคือฉันไม่พบสิ่งใดใน. Net API เนื่องจากมีรูปแบบและตำแหน่งมากมายที่ Windows รองรับฉันจึงควรใช้ MS-native

เนื่องจากฟังก์ชันควรสามารถตรวจสอบกับ:

  • เส้นทางสัมพัทธ์ (./)
  • เส้นทางสัมบูรณ์ (c: \ tmp)
  • UNC-Pathes (\ some-pc \ c $)
  • NTFS- ข้อ จำกัด เช่นเส้นทางแบบเต็ม 1024 ตัวอักษร - ถ้าฉันไม่เข้าใจผิดเกินพา ธ จะทำให้ไฟล์ไม่สามารถเข้าถึงได้สำหรับฟังก์ชั่นภายในของ Windows จำนวนมาก การเปลี่ยนชื่อด้วย Explorer ยังคงใช้งานได้
  • เส้นทาง GUID ของไดรฟ์ข้อมูล: "\? \ Volume {GUID} \ somefile.foo

ใครมีฟังก์ชั่นแบบนี้บ้าง?


คำตอบ:


58

ลองUri.IsWellFormedUriString():

  • ไม่สามารถหลีกเลี่ยงสตริงได้อย่างถูกต้อง

    http://www.example.com/path???/file name
  • สตริงคือ Uri สัมบูรณ์ที่แสดงถึงไฟล์โดยนัย Uri

    c:\\directory\filename
  • สตริงคือ URI สัมบูรณ์ที่ไม่มีเครื่องหมายทับก่อนพา ธ

    file://c:/directory/filename
  • สตริงมีแบ็กสแลชที่ไม่ใช้ Escape แม้ว่าจะถือว่าเป็นเครื่องหมายทับ

    http:\\host/path/file
  • สตริงแสดงถึง Uri สัมบูรณ์แบบลำดับชั้นและไม่มี ": //"

    www.example.com/path/file
  • ตัวแยกวิเคราะห์สำหรับ Uri.Scheme บ่งชี้ว่าสตริงเดิมมีรูปแบบไม่ถูกต้อง

    The example depends on the scheme of the URI.

9
สิ่งนี้ส่งคืนเท็จสำหรับ@"foo\bar\baz"ซึ่งเป็นเส้นทางสัมพัทธ์ที่ถูกต้องอย่างสมบูรณ์ ...
Thomas Levesque

5
Thomas: คุณระบุ UriKind อะไร? คุณสามารถใช้ Absolute, Relative หรือ AbsoluteOrRelative
Dan Gøran Lunde

1
แม้ว่า UriKind เป็นญาติหรือ AbsoluteOrRelative ก็ไม่ได้ผลกับเส้นทางสัมพัทธ์อย่างที่โทมัสกล่าวถึง ฉันลงเอยด้วยการใช้คำตอบของ Patko แทนและใช้ได้ตามวัตถุประสงค์ของฉัน
JohnnyM

1
ฉันพบว่าเส้นทางเช่น \\ computerName \ Dir Name With Spaces \ fileName แสดงข้อยกเว้นเมื่อใช้ IsWellFormedUriString (ตรงกันข้ามกับความคาดหวังเริ่มต้นของฉัน) เนื่องจากช่องว่างไม่ได้เข้ารหัสอย่างถูกต้อง ฉันพบว่าฉันสามารถใช้ตัวสร้าง Uri (สตริง) เป็นการตรวจสอบความถูกต้องของฉันได้ดังนั้นไม่จำเป็นต้องเข้ารหัสสตริงอย่างถูกต้องก่อนที่จะตรวจสอบความถูกต้อง
แก่นสาร 5

3
ส่งคืนเท็จบนพา ธ ไฟล์ที่ดีอย่างสมบูรณ์
Evgeni Petrov

29

หรือใช้FileInfoตามที่แนะนำในใน C # ตรวจสอบว่าชื่อไฟล์คืออาจจะเป็นที่ถูกต้อง (ไม่ได้ว่ามันมีอยู่)


การใช้โซลูชันที่โพสต์โดย "LamdaComplex" ในชุดข้อความเดียวกันดูเหมือนจะแม่นยำกว่า: stackoverflow.com/a/11636052/2546739
Xav987

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

ฉันไม่มีปัญหากับรหัสด้านล่างนี้ (พา ธ สัมพัทธ์ต้องขึ้นต้นด้วย "/" หรือ "\")

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

ตัวอย่างเช่นสิ่งเหล่านี้จะส่งคืนเท็จ:

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

และสิ่งเหล่านี้จะกลับมาเป็นจริง:

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

คุณสามารถลองใช้รหัสนี้:

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

ไม่แน่ใจว่าครอบคลุมทุกกรณีไหม ...


2

สิ่งที่ใกล้เคียงที่สุดที่ฉันได้มาคือการพยายามสร้างมันขึ้นมาและดูว่ามันสำเร็จหรือไม่


2

มีวิธีแก้ปัญหาที่ดีมากมายในที่นี้ แต่ถ้าไม่มีให้ตรวจสอบว่าเส้นทางนั้นถูกรูทในไดรฟ์ที่มีอยู่หรือไม่นี่คืออีกวิธีหนึ่ง:

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

โซลูชันนี้ไม่ได้คำนึงถึงเส้นทางสัมพัทธ์


1

รับตัวอักษรที่ไม่ถูกต้องจากSystem.IO.Path.GetInvalidPathChars();และตรวจสอบว่าสตริง (เส้นทางไดเรกทอรี) ของคุณมีสิ่งเหล่านี้หรือไม่


3
สิ่งนี้ไม่ถูกต้องทั้งหมด "C: \ new.folder" ใช้ได้ในขณะที่ "C: \ newfolder" ไม่ใช่. '.' เป็นอักขระที่ถูกต้องสำหรับพา ธ / ชื่อไฟล์ แต่ไม่ใช่ที่ส่วนท้ายของ uri
claudekennilol

0

4
"[... ] ไม่ต้องการตรวจสอบว่ามีไฟล์อยู่หรือไม่!"
Stefan

3
การทดสอบนั้นสำหรับไดเร็กทอรีที่มีอยู่ไม่ใช่เพราะเป็นเส้นทางที่ถูกต้อง (ซึ่งอาจมีอยู่หรือถูกสร้างขึ้นโดยให้สิทธิ์ที่เหมาะสม)
Martijn

3
@ Jason - ไม่ได้ตรวจสอบไฟล์เฉพาะโฟลเดอร์ที่มี
markpsmith

8
แต่เส้นทางไดเร็กทอรีที่ถูกต้องยังคงไม่มีอยู่
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
จุดประสงค์ของ x1 คืออะไร?
JayJay


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.