developer tip

전체 경로가 제공되었는지 확인하십시오.

copycodes 2020. 8. 23. 09:23
반응형

전체 경로가 제공되었는지 확인하십시오.


주어진 경로가 전체 경로인지 확인하는 방법이 있습니까? 지금 나는 이것을하고있다 :

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

그러나 이것을 확인하는 더 우아한 방법이 있어야합니까?


사용 System.IO.Path.IsPathRooted하시겠습니까? true절대 경로에 대해서도 반환 됩니다.

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"

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

위의 조건 :

  • 파일 시스템 권한이 필요하지 않습니다.
  • false형식 path이 유효하지 않은 대부분의 경우를 반환합니다 (예외를 던지는 대신).
  • 볼륨 truepath포함 된 경우에만 반환

OP가 제시 한 시나리오와 같은 시나리오에서는 이전 답변의 조건보다 더 적합 할 수 있습니다. 위의 조건과 달리 :

  • path == System.IO.Path.GetFullPath(path)false다음 시나리오에서 반환하지 않고 예외를 throw합니다 .
    • 발신자에게 필요한 권한이 없습니다.
    • 시스템이 절대 경로를 검색 할 수 없습니다.
    • 경로에 볼륨 식별자의 일부가 아닌 콜론 ( ":")이 있습니다.
    • 지정된 경로, 파일 이름 또는 둘 다 시스템 정의 최대 길이를 초과합니다.
  • System.IO.Path.IsPathRooted(path)단일 디렉토리 구분자로 시작 true하면 반환 합니다 path.

마지막으로, 다음은 위의 조건을 래핑하고 가능한 나머지 예외도 차단하는 메서드입니다.

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

편집 : EM0은 및와 같은 흥미로운 경우를 해결 하는 좋은 의견과 대안 답변C: 을 작성했습니다 C:dir. 이러한 경로를 처리하는 방법을 결정하는 데 도움이되도록 MSDN-> Windows 데스크톱 응용 프로그램 -> 개발 -> 데스크톱 기술 -> 데이터 액세스 및 저장소 -> 로컬 파일 시스템 -에 대해 자세히 살펴볼 수 있습니다. -> 파일 관리 -> 파일 관리 정보 -> 작성, 삭제 및 파일 유지 -> 파일, 경로 및 네임 스페이스 명명 -> 정규화 대 상대 경로

파일을 조작하는 Windows API 함수의 경우 파일 이름은 종종 현재 디렉토리에 상대적 일 수 있지만 일부 API에는 완전한 경로가 필요합니다. 다음 중 하나로 시작하지 않는 파일 이름은 현재 디렉토리에 상대적입니다.

  • 항상 두 개의 백 슬래시 문자 ( "\")로 시작하는 모든 형식의 UNC 이름. 자세한 내용은 다음 섹션을 참조하십시오.
  • 백 슬래시가있는 디스크 지정자 (예 : "C : \"또는 "d : \").
  • 단일 백 슬래시 (예 : "\ directory"또는 "\ file.txt") 이것은 절대 경로라고도합니다.

파일 이름이 디스크 지정 자로 만 시작되고 콜론 뒤의 백 슬래시가 아닌 경우, 지정된 문자가있는 드라이브의 현재 디렉토리에 대한 상대 경로로 해석됩니다. 현재 디렉토리는 해당 디스크에서 가장 최근의 "디렉토리 변경"작업 중에 설정된 항목에 따라 루트 디렉토리 일 수도 있고 아닐 수도 있습니다. 이 형식의 예는 다음과 같습니다.

  • "C : tmp.txt"는 C 드라이브의 현재 디렉토리에있는 "tmp.txt"라는 파일을 나타냅니다.
  • "C : tempdir \ tmp.txt"는 C 드라이브의 현재 디렉터리에 대한 하위 디렉터리의 파일을 나타냅니다.

[...]


시험

System.IO.Path.IsPathRooted(template)

UNC 경로 및 로컬 경로에 대해 작동합니다.

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

이전 질문이지만 적용 가능한 답변이 하나 더 있습니다. 볼륨이 로컬 경로에 포함되어 있는지 확인해야하는 경우 다음과 같이 System.IO.Path.GetFullPath ()를 사용할 수 있습니다.

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
}

Building on weir's answer: this does not throw for invalid paths, but also returns false for paths like "C:", "C:dirname" and "\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
}

Note that this returns different results on Windows and Linux, e.g. "/path" is absolute on Linux, but not on Windows.

Unit test:

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

To check whether a path is fully qualified (MSDN):

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

It's a bit simpler than what's already been proposed, and it still returns false for drive-relative paths like C:foo. Its logic is based directly on the MSDN definition of "fully qualified", and I haven't found any examples it misbehaves on.


Interestingly however, .NET Core 2.1 seems to have a new method Path.IsPathFullyQualified which uses an internal method PathInternal.IsPartiallyQualified (link location accurate as of 2018-04-17).

For posterity and better self-containment of this post, here's the latter's implementation for reference:

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

This is the solution I use

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

It works the following way:

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

I'm not really sure what you mean by full path (though assuming from the example you mean non-relative from the root onwards), well, you can use the Path class to aid you in working with physical filesystem paths, which should cover you for most eventualities.


Call the following function:

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

MSDN doc: Path.IsPathFullyQualified Method

The useful cite from MSDN doc follows:

This method handles paths that use the alternate directory separator. It's a frequent mistake to assume that rooted paths (IsPathRooted(String)) aren't relative. For example, "C:a" is drive relative, that is, it's resolved against the current directory for C: (rooted, but relative). "C:\a" is rooted and not relative, that is, the current directory isn't used to modify the path.

참고URL : https://stackoverflow.com/questions/5565029/check-if-full-path-given

반응형