DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

絶対パスか相対パスか調べる

ここでは、指定されたパス(文字列)が絶対パス(フルパス)か相対パスかを調べる方法を紹介します。

なおここでは、基本的には、パスとして正しくない文字列がパスとして指定されることは考慮しません。文字列がパスとして正しいかどうか調べる方法は、「ファイル名に使用できない文字列が含まれていないか調べる」等を参考にしてください。

Path.IsPathRootedメソッドを使用する方法

.NET Frameworkで用意されているメソッドの中では、Path.IsPathRootedメソッドがその目的に一番近いでしょう。IsPathRootedメソッドがTrueを返せば絶対パス、Falseを返せば相対パスと判断できます。

このメソッドは、指定されたパスに不正な文字(Path.GetInvalidPathCharsメソッドで定義されている文字)が使われていないかをチェックして、使われていれば例外ArgumentExceptionをスローします。

このメソッドは、指定された文字列の1文字目が「\」(または、「/」)か、2文字目が「:」の時にTrueを返すようです。よって、例えば「\file.txt」(カレントドライブのルートにあるfile.txt)や、「C:file.txt」(ドライブCのカレントディレクトリにあるfile.txt)でもTrueを返します。もしこれらのパスを相対パスと判断したいのであれば、このメソッドだけでは不十分です。

補足:この問題は、MSDNの「Path.IsPathRooted Method (System.IO)」にあるCommunity Additionsで指摘されています。その影響か、MSDNでのPath.IsPathRootedメソッドの説明は、.NET Framework 3.5までは、「指定したパス文字列に絶対パス情報または相対パスの情報が含まれているかを示す値を取得します。」でしたが、.NET Framework 4.0からは、「指定したパス文字列にルートが含まれているかどうかを示す値を取得します。」に変わりました。

以下に、Path.IsPathRootedメソッドの使用例と、その結果を幾つか示します。

VB.NET
コードを隠すコードを選択
'Imports System.IO

Console.WriteLine(Path.IsPathRooted("C:\file.txt"))         'true
Console.WriteLine(Path.IsPathRooted("\\pc\s\file.txt"))     'true
Console.WriteLine(Path.IsPathRooted("\file.txt"))           'true
Console.WriteLine(Path.IsPathRooted("file.txt"))            'false
Console.WriteLine(Path.IsPathRooted(".\file.txt"))          'false
Console.WriteLine(Path.IsPathRooted("..\file.txt"))         'false
Console.WriteLine(Path.IsPathRooted("C:file.txt"))          'true
C#
コードを隠すコードを選択
//using System.IO;

Console.WriteLine(Path.IsPathRooted(@"C:\file.txt"));       //true
Console.WriteLine(Path.IsPathRooted(@"\\pc\s\file.txt"));   //true
Console.WriteLine(Path.IsPathRooted(@"\file.txt"));         //true
Console.WriteLine(Path.IsPathRooted(@"file.txt"));          //false
Console.WriteLine(Path.IsPathRooted(@".\file.txt"));        //false
Console.WriteLine(Path.IsPathRooted(@"..\file.txt"));       //false
Console.WriteLine(Path.IsPathRooted(@"C:file.txt"));        //true

自分で判断する方法

Naming Files, Paths, and Namespaces (Windows)」によると、「\\」で始まるか、「:\」を含むか、「\」で始まっているパス以外のパスは、カレントディレクトリからの相対パスになるということです。

この内「\」で始まるパスは、通常相対パスと判断したいところですので、ここでは「\\」で始まるか、2文字目以降が「:\」である場合のみ絶対パスと判断することにして、メソッドを作ってみました。

VB.NET
コードを隠すコードを選択
'Imports System.IO

''' <summary>
''' 指定したパス文字列が絶対パスか相対パスかを判断する。
''' </summary>
''' <param name="p">判断するパス。</param>
''' <returns>絶対パスと判断した場合は、True。それ以外は、False。</returns>
Public Shared Function IsAbsolatePath(p As String) As Boolean
    Dim len As Integer = p.Length
    If (2 <= len AndAlso _
        (p(0) = Path.DirectorySeparatorChar OrElse _
             p(0) = Path.AltDirectorySeparatorChar) AndAlso _
        (p(1) = Path.DirectorySeparatorChar OrElse _
            p(1) = Path.AltDirectorySeparatorChar)) OrElse _
        (3 <= len AndAlso _
        p(1) = Path.VolumeSeparatorChar AndAlso _
        (p(2) = Path.DirectorySeparatorChar OrElse _
            p(2) = Path.AltDirectorySeparatorChar)) Then
        Return True
    End If
    Return False
End Function
C#
コードを隠すコードを選択
//using System.IO;

/// <summary>
/// 指定したパス文字列が絶対パスか相対パスかを判断する。
/// </summary>
/// <param name="p">判断するパス。</param>
/// <returns>絶対パスと判断した場合は、True。それ以外は、False。</returns>
public static bool IsAbsolatePath(string p)
{
    int len = p.Length;
    if ((2 <= len &&
        (p[0] == Path.DirectorySeparatorChar ||
            p[0] == Path.AltDirectorySeparatorChar) &&
        (p[1] == Path.DirectorySeparatorChar ||
            p[1] == Path.AltDirectorySeparatorChar)) ||
        (3 <= len &&
        p[1] == Path.VolumeSeparatorChar &&
        (p[2] == Path.DirectorySeparatorChar ||
            p[2] == Path.AltDirectorySeparatorChar)))
    {
        return true;
    }
    return false;
}

Path.GetFullPathメソッドの結果と比較する

Path.GetFullPathメソッドは、相対パスを渡すと絶対パスを返し、絶対パスを渡すとそのまま返します。よって、Path.GetFullPathメソッドに渡したパスと返されたパスが同じ場合は絶対パス、異なる場合は相対パスと判断できます。

ただしこのメソッドは、短いファイル名を渡すと長いファイル名に変換したり、パスに「..」や「.」が含まれていると正規化したりするため、渡したパスが絶対パスでもそれとは異なるパス文字列を返す可能性があります。

このメソッドは、Path.IsPathRootedメソッドと同様、パスとして不正な文字が含まれていないか調べる他、パスの長さなど、パスとして正しいかをある程度チェックし、正しくなければ例外をスローします。また、パスが存在する場合はファイルシステムにアクセスし、アクセスできない時は例外SecurityExceptionをスローします。

VB.NET
コードを隠すコードを選択
'Imports System.IO

'絶対パスか調べるパス
Dim p As String = "c:\dir\file.txt"
'GetFullPathメソッドが同じ文字列を返したら、絶対パスと判断する
If Path.GetFullPath(p).Equals(p) Then
    Console.WriteLine("絶対パスです。")
Else
    Console.WriteLine("絶対パスではありません。")
End If
C#
コードを隠すコードを選択
//using System.IO;

//絶対パスか調べるパス
string p = @"c:\dir\file.txt";
//GetFullPathメソッドが同じ文字列を返したら、絶対パスと判断する
if (Path.GetFullPath(p).Equals(p))
{
    Console.WriteLine("絶対パスです。");
}
else
{
    Console.WriteLine("絶対パスではありません。");
}

Uri.TryCreateメソッドを使用する方法

Uriコンストラクタの1番目の引数にパスを、2番目の引数にUriKind.Absoluteを指定すると、パスが相対パスだった場合に例外がスローされます。Uriコンストラクタの代わりにUri.TryCreateメソッドを使用すると、例外を発生することなく、その確認ができます。このメソッドは、.NET Framework 2.0以降で使用できます。

基本的には、このメソッドで調べるのは指定されたURIが正しいか(Uriオブジェクトを作成できるか)ですが、Windowsパスも指定できます。また、今まで紹介してきた方法では「file:///」形式のパスを正しく判断できませんが、この方法ではできます(できない方が良いかもしれませんが...)。

このメソッドは「http://」などのURIでもTrueを返しますが、Windowsパスや「file:///」であることを確認するなら、作成されたUriオブジェクトのIsFileプロパティを調べればよいでしょう。また、IsUncプロパティによって、UNCパスかどうかが分かります。

VB.NET
コードを隠すコードを選択
Dim u As Uri
Console.WriteLine(Uri.TryCreate("C:\file.txt", UriKind.Absolute, u))
'true
Console.WriteLine(Uri.TryCreate("\\pc\s\file.txt", UriKind.Absolute, u))
'true
Console.WriteLine(Uri.TryCreate("\file.txt", UriKind.Absolute, u))
'false
Console.WriteLine(Uri.TryCreate("file.txt", UriKind.Absolute, u))
'false
Console.WriteLine(Uri.TryCreate(".\file.txt", UriKind.Absolute, u))
'false
Console.WriteLine(Uri.TryCreate("..\file.txt", UriKind.Absolute, u))
'false
Console.WriteLine(Uri.TryCreate("C:file.txt", UriKind.Absolute, u))
'false
Console.WriteLine(Uri.TryCreate("file:///C:/file.txt", UriKind.Absolute, u))
'true
C#
コードを隠すコードを選択
Uri u;
Console.WriteLine(Uri.TryCreate(@"C:\file.txt", UriKind.Absolute, out u));
//true
Console.WriteLine(Uri.TryCreate(@"\\pc\s\file.txt", UriKind.Absolute, out u));
//true
Console.WriteLine(Uri.TryCreate(@"\file.txt", UriKind.Absolute, out u));
//false
Console.WriteLine(Uri.TryCreate(@"file.txt", UriKind.Absolute, out u));
//false
Console.WriteLine(Uri.TryCreate(@".\file.txt", UriKind.Absolute, out u));
//false
Console.WriteLine(Uri.TryCreate(@"..\file.txt", UriKind.Absolute, out u));
//false
Console.WriteLine(Uri.TryCreate(@"C:file.txt", UriKind.Absolute, out u));
//false
Console.WriteLine(Uri.TryCreate(@"file:///C:/file.txt", UriKind.Absolute, out u));
//true

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • コードの先頭に記述されている「Imports ??? がソースファイルの一番上に書かれているものとする」(C#では、「using ???; がソースファイルの一番上に書かれているものとする」)の意味が分からないという方は、こちらをご覧ください。
  • Windows Vista以降でUACが有効になっていると、ファイルへの書き込みに失敗する可能性があります。詳しくは、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。