using System; namespace Wankuma.IO { /// /// Path関連のクラスです。 /// public class Path { /// /// 絶対パス2つから相対パスを導き出します。 /// /// /// /// public static string PathAbsoluteRelative(string BasePath, string TargetPath) { //パスのルートが同じでないと相対化できないので、お互いのルートを調べて例外を発生させる string BasePathRoot = System.IO.Path.GetPathRoot(BasePath); string TargetPathRoot = System.IO.Path.GetPathRoot(TargetPath); if ( BasePathRoot != TargetPathRoot ) { throw new ArgumentException("双方のパスが関連のないパスです。", "BasePath TargetPath"); } string[] BasePathSplit; string[] TargetPathSplit; { //c:\a\等の場合には最後の区切り文字のせいで、誤判定をするので削除する string BasePathWithOutEndsSeparator = RemoveEndsSeparator(BasePath); string TargetPathWithOutEndsSeparator = RemoveEndsSeparator(TargetPath); //ルート部分を両方から切除します string BasePathWithOutRoot = BasePathWithOutEndsSeparator.Substring(BasePathRoot.Length); string TargetPathWithOutRoot = TargetPathWithOutEndsSeparator.Substring(BasePathRoot.Length); //UNCの場合には先頭文字が\マークで終わってしまうので、先頭の\マークも除去する if ( BasePathWithOutRoot[0] == '\\' ) { BasePathWithOutRoot = BasePathWithOutRoot.Substring(1); } if ( TargetPathWithOutRoot[0] == '\\' ) { TargetPathWithOutRoot = TargetPathWithOutRoot.Substring(1); } //パス区切り文字で分割します。 BasePathSplit = BasePathWithOutRoot.Split(System.IO.Path.DirectorySeparatorChar ); TargetPathSplit = TargetPathWithOutRoot.Split(System.IO.Path.DirectorySeparatorChar ); } int LoopCounter = 0; for ( LoopCounter = 0; LoopCounter < BasePathSplit.Length; LoopCounter++ ) { if ( TargetPathSplit.Length <= LoopCounter) { break; } //二つのパス文字列を比較する、同じであれば問題ないが、同じでなければそこでパスの同一性が失われたことになり、breakする if ( BasePathSplit[LoopCounter] != TargetPathSplit[LoopCounter] ) { break; } } bool UpperFlag = false; bool BelowFlag = false; if ( BasePathSplit.Length > LoopCounter && TargetPathSplit.Length > LoopCounter ) { //どちらでもないという場合には根が同じ分岐されたディレクトリと判断できる System.Diagnostics.Debug.WriteLine("分岐"); UpperFlag = true; BelowFlag = true; } else if ( BasePathSplit.Length > LoopCounter ) { //ベースパスの方が長い場合対象パスはベースパスより上にあると判断できる System.Diagnostics.Debug.WriteLine("上"); UpperFlag = true; } else if ( TargetPathSplit.Length > LoopCounter ) { //対象の方が長いという場合にはベースより下にあると判断できる System.Diagnostics.Debug.WriteLine("下"); BelowFlag = true; } else { throw new Exception(); } PathBuilder pb = new PathBuilder(); //パスの連結作業を行う if ( UpperFlag == true ) { for ( int UppePathLoopCounter = 0; UppePathLoopCounter < BasePathSplit.Length - LoopCounter; UppePathLoopCounter++) { pb.Append(".."); } } if ( BelowFlag == true ) { for ( int BelowPathLoopCounter = LoopCounter ; BelowPathLoopCounter < TargetPathSplit.Length; BelowPathLoopCounter++ ) { pb.Append(TargetPathSplit[BelowPathLoopCounter]); } } return pb.ToString(); } /// /// パス文字列の最後の文字が区切り文字でなければ区切り文字を追加します /// c:\ -> c:\, c:\a -> c:\a\ /// /// 対象のパス文字列 /// 区切り文字付加済みのパス文字列 public static string AddEndsSeparator(string path) { if ( path == null ) { throw new ArgumentNullException("path", "pathにnullは指定できません"); } if ( path == string.Empty ) { throw new ArgumentException("path", "pathはemptyに出来ません。"); } if ( path.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString()) == true ) { return path; } else { return path + System.IO.Path.DirectorySeparatorChar; } } /// /// パス文字列の最後の文字が区切り文字であれば区切り文字を削除します /// c:\ -> c:, c:\a -> c:\a /// c:\等の場合には意図しない動作をする可能性があるので注意。あくまで文字列の最後の文字だけを判定します。 /// /// 対象のパス文字列 /// 区切り文字削除済みのパス文字列 public static string RemoveEndsSeparator(string path) { if ( path == null ) { throw new ArgumentNullException("path", "pathにnullは指定できません"); } if ( path == string.Empty ) { throw new ArgumentException("path", "pathはemptyに出来ません。"); } if ( path.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString()) == true ) { return path.Substring(0, path.Length - 1); } else { return path; } } } }