Kiểm tra xem đường dẫn có hợp lệ không


110

Tôi chỉ đang tự hỏi: Tôi đang tìm cách xác nhận xem một đường dẫn đã cho có hợp lệ hay không. (Lưu ý: Tôi không muốn kiểm tra xem tệp có tồn tại hay không! Tôi chỉ muốn chứng minh tính hợp lệ của đường dẫn - Vì vậy, nếu tệp có thể tồn tại ở vị trí) .

Vấn đề là tôi không thể tìm thấy bất kỳ thứ gì trong .Net API. Do nhiều định dạng và vị trí mà Windows hỗ trợ, tôi muốn sử dụng một thứ gì đó MS-native.

Vì hàm sẽ có thể kiểm tra:

  • Đường dẫn tương đối (./)
  • Đường dẫn Tuyệt đối (c: \ tmp)
  • UNC-Pathes (\ some-pc \ c $)
  • NTFS-Hạn chế như đường dẫn đầy đủ 1024 ký tự - Nếu tôi không nhầm thì việc vượt quá đường dẫn sẽ khiến tệp không thể truy cập được đối với nhiều chức năng nội bộ của Windows. Đổi tên nó bằng Explorer vẫn hoạt động
  • Đường dẫn GUID âm lượng: "\? \ Volume {GUID} \ somefile.foo

Có ai có một chức năng như thế này?


Câu trả lời:


58

Hãy thử Uri.IsWellFormedUriString():

  • Chuỗi không được thoát đúng cách.

    http://www.example.com/path???/file name
  • Chuỗi là một Uri tuyệt đối đại diện cho một Uri tệp ngầm định.

    c:\\directory\filename
  • Chuỗi là một URI tuyệt đối thiếu dấu gạch chéo trước đường dẫn.

    file://c:/directory/filename
  • Chuỗi chứa các dấu gạch chéo ngược không thoát ngay cả khi chúng được coi là dấu gạch chéo ngược.

    http:\\host/path/file
  • Chuỗi đại diện cho một Uri tuyệt đối phân cấp và không chứa ": //".

    www.example.com/path/file
  • Trình phân tích cú pháp cho Uri.Scheme chỉ ra rằng chuỗi ban đầu không được định dạng tốt.

    The example depends on the scheme of the URI.

9
Đây false trả cho @"foo\bar\baz", mà là một đường dẫn tương đối hoàn toàn hợp lệ ...
Thomas Levesque

5
Thomas: Bạn đã chỉ định UriKind gì? Bạn có thể sử dụng Absolute, Relative hoặc AbsoluteOrRelative.
Dan Gøran Lunde,

1
Ngay cả với UriKind là Relative hoặc AbsoluteOrRelative, nó không hoạt động với các đường dẫn tương đối như Thomas đã đề cập. Tôi đã kết thúc bằng cách sử dụng câu trả lời của Patko thay vì nó hoạt động cho mục đích của tôi.
JohnnyM

1
Tôi nhận thấy rằng một đường dẫn như \\ computerName \ Dir Name With Spaces \ fileName ném ra một ngoại lệ khi sử dụng IsWellFormedUriString (trái với kỳ vọng ban đầu của tôi), vì các khoảng trắng không được mã hóa đúng cách. Tôi thấy rằng tôi chỉ có thể sử dụng hàm tạo Uri (chuỗi) làm xác thực của mình, do đó, không cần phải mã hóa đúng chuỗi trước khi xác thực.
tinh túy

3
Trả về false trên đường dẫn tệp hoàn toàn tốt.
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

Tôi không gặp bất kỳ vấn đề nào với mã bên dưới. (Các đường dẫn tương đối phải bắt đầu bằng '/' hoặc '\').

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

Ví dụ, những điều này sẽ trả về 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);

Và những điều này sẽ trả về 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

Bạn có thể thử mã này:

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

Tôi không chắc nó bao gồm tất cả các trường hợp ...


2

Điều gần nhất tôi đã đến là cố gắng tạo ra nó và xem nó có thành công hay không.


2

Có rất nhiều giải pháp tốt ở đây, nhưng không có giải pháp nào sau đó kiểm tra xem đường dẫn có bắt nguồn từ ổ đĩa hiện có hay không, đây là một giải pháp khác:

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

Giải pháp này không tính đến các đường dẫn tương đối.


1

Lấy các ký tự không hợp lệ từ đó System.IO.Path.GetInvalidPathChars();và kiểm tra xem chuỗi của bạn (Đường dẫn thư mục) có chứa những ký tự đó hay không.


3
Điều này không hoàn toàn hợp lệ. "C: \ new.folder" hợp lệ trong khi "C: \ newfolder." không phải. '.' là một ký tự hợp lệ cho một đường dẫn / tên tệp, nhưng không phải ở cuối tiểu.
claudekennilol

0

4
"[...] không muốn kiểm tra xem có tập tin nào không!"
Stefan

3
Đó là thử nghiệm cho thư mục hiện hành, không cho nó là một đường dẫn hợp lệ (nơi người ta có thể tồn tại, hoặc được tạo ra, trao đặc quyền thích hợp)
Martijn

3
@Jason - Nó không kiểm tra tệp, chỉ kiểm tra thư mục chứa.
thợ đánh dấu

8
nhưng một đường dẫn thư mục hợp lệ vẫn không thể tồn tại.
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
mục đích của x1 là gì?
JayJay

-3

Chỉ cần sử dụng đơn giản

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

-4

Bạn có thể thử sử dụng Path.IsPathRooted () kết hợp với Path.GetInvalidFileNameChars () để đảm bảo rằng đường dẫn vẫn ổn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.