วิธีการแปลงเส้นทางสัมพัทธ์เป็นเส้นทางสัมบูรณ์ในแอปพลิเคชัน Windows


92

ฉันจะแปลงเส้นทางสัมพัทธ์เป็นเส้นทางสัมบูรณ์ในแอปพลิเคชัน Windows ได้อย่างไร

ฉันรู้ว่าเราสามารถใช้ server.MapPath () ใน ASP.NET แต่เราสามารถทำอะไรได้บ้างในแอปพลิเคชัน Windows?

ฉันหมายถึงถ้ามีฟังก์ชัน. NET ในตัวที่สามารถจัดการสิ่งนั้นได้ ...


2
คุณหมายถึงเส้นทางสัมพัทธ์ไปยังไดเร็กทอรีปัจจุบันหรืออีกนัยหนึ่งคือไดเร็กทอรีการทำงานหรือสัมพันธ์กับตำแหน่งของ. exe?
Tobias Hertkorn

2
เส้นทางสัมพัทธ์มีสองชนิด ถ้าอยู่ในรูปแบบ "A \ B \ C" และไม่ได้หมายความถึงฐานเฉพาะ อีกอันมีรูปแบบ ". \ A \ B" หรือ ".. \ A \ B"; สิ่งเหล่านี้สัมพันธ์กับไดเร็กทอรีการทำงานปัจจุบัน
MSalters

1
@Amit Dhall: อย่างไรก็ตามมันเป็นสิ่งที่ดีที่จะยอมรับและเพิ่มคะแนนคำตอบที่ช่วยคุณ
Francis B.

คำตอบ:


184

คุณได้ลอง:

string absolute = Path.GetFullPath(relative);

เหรอ? โปรดทราบว่าจะใช้ไดเร็กทอรีการทำงานปัจจุบันของกระบวนการไม่ใช่ไดเร็กทอรีที่มีไฟล์ปฏิบัติการ หากไม่ได้ผลโปรดชี้แจงคำถามของคุณ


4
นั่นจะไม่ขึ้นอยู่กับว่าคุณเริ่มต้นแอพจากที่ไหนไม่ใช่ขึ้นอยู่กับว่า exe อยู่ที่ไหน ได้รับคำถามที่ไม่ชัดเจนจริงๆเกี่ยวกับเรื่องนี้
Tobias Hertkorn

1
อย่างที่คุณพูดคำถามไม่ชัดเจน GetFullPath จะแก้ไขจากไดเร็กทอรีการทำงานปัจจุบัน ฉันจะแก้ไขคำตอบของฉันเพื่อระบุสิ่งนี้
Jon Skeet

1
หากแอปพลิเคชันเริ่มทำงานผ่าน Windows Explorer ดูเหมือนว่าไดเร็กทอรีปัจจุบันและไดเร็กทอรีแอสเซมบลีการเรียกใช้งานจะเหมือนกัน (อย่างน้อยก็จนกว่าจะมีการทำบางอย่างเพื่อให้แตกต่างกัน) นี่เป็นความจริงแม้ว่าคุณจะใช้ช็อตคัทไปยังไฟล์ปฏิบัติการที่ช็อตคัทอยู่ที่ไหนสักแห่งที่แตกต่างไปจากเดิมอย่างสิ้นเชิง
H2ONaCl

19

หากคุณต้องการรับเส้นทางที่สัมพันธ์กับ. exe ของคุณให้ใช้

string absolute = Path.Combine(Application.ExecutablePath, relative);

4
ระวังด้วย Path.Combine หากส่วน "สัมพัทธ์" เริ่มต้นด้วยเครื่องหมายทับแสดงว่าอาจไม่ทำอย่างที่คุณคิด
เที่ยงผ้าไหม

2
@silky: ถ้าอย่างนั้นมันก็ไม่ใช่ญาติใช่มั้ย?
Tor Haugen

1
ดูเหมือนว่าPath.Combineไม่สามารถจัดการเส้นทางที่สัมพันธ์กับไดรฟ์ได้ มันไม่สนใจเส้นทางเริ่มต้นที่ดูเหมือน ฉันกำลังโพสต์วิธีแก้ปัญหาทั้งหมดของตัวเอง
Nyerguds

3
สิ่งนี้ไม่สามารถจัดการเส้นทางสัมพัทธ์ ยอมรับไดเร็กทอรีและชื่อไฟล์เท่านั้น หากอาร์กิวเมนต์ที่สองเริ่มต้นด้วยสิ่งที่ต้องการ..มันจะทำให้เกิดขยะ
Jonathan Wood

1
@JonathanWood ที่จริง "ขยะ" (เส้นทางที่รวม..อยู่ในนั้น) ได้รับการยอมรับและแก้ไขอย่างสมบูรณ์แบบโดยระบบจัดการไฟล์ทั้งหมดใน. Net หากมันรบกวนคุณให้ดำเนินการabsolute = Path.GetFullPath(absolute)กับมัน
Nyerguds

15

วิธีนี้ใช้ได้กับเส้นทางบนไดรฟ์ที่แตกต่างกันสำหรับเส้นทางที่สัมพันธ์กับไดรฟ์และสำหรับเส้นทางสัมพัทธ์จริง Heck แม้จะใช้งานได้หากbasePathไม่ได้เป็นแบบสัมบูรณ์จริง จะใช้ไดเร็กทอรีการทำงานปัจจุบันเป็นทางเลือกสุดท้ายเสมอ

public static String GetAbsolutePath(String path)
{
    return GetAbsolutePath(null, path);
}

public static String GetAbsolutePath(String basePath, String path)
{
    if (path == null)
        return null;
    if (basePath == null)
        basePath = Path.GetFullPath("."); // quick way of getting current working directory
    else
        basePath = GetAbsolutePath(null, basePath); // to be REALLY sure ;)
    String finalPath;
    // specific for windows paths starting on \ - they need the drive added to them.
    // I constructed this piece like this for possible Mono support.
    if (!Path.IsPathRooted(path) || "\\".Equals(Path.GetPathRoot(path)))
    {
        if (path.StartsWith(Path.DirectorySeparatorChar.ToString()))
            finalPath = Path.Combine(Path.GetPathRoot(basePath), path.TrimStart(Path.DirectorySeparatorChar));
        else
            finalPath = Path.Combine(basePath, path);
    }
    else
        finalPath = path;
    // resolves any internal "..\" to get the true full path.
    return Path.GetFullPath(finalPath);
}

1
ทางออกที่ดีเพราะรวมเส้นทางสัมบูรณ์หรือญาติตามเส้นทางฐาน ในความคิดของฉันอาร์กิวเมนต์ relativePath ควรเปลี่ยนชื่อเป็น AbsoluteOrRelativePath เนื่องจากเป็นสิ่งที่แสดงถึง ขอบคุณ
Julio Nobre

1
ถ้ามันเป็นพา ธ สัมบูรณ์อยู่แล้วนั่นเป็นเพียงกรณีพิเศษจริงๆ ... ฟังก์ชันนี้ยังคงหมายถึงการแก้ไขพา ธ สัมพัทธ์ฮ่า ๆ ฉันเพิ่งตั้งชื่อมันว่าที่นี่เพื่อให้ชัดเจนว่าพารามิเตอร์ใดคือพารามิเตอร์ใด;)
Nyerguds

1
@JulioNobre โดยเฉพาะอย่างยิ่งเนื่องจาก args ที่นี่จะกลับรายการเมื่อเทียบกับPath.Combine. แก้ไขได้ง่าย แต่ฉันหลีกเลี่ยงเนื่องจากฉันมักใช้เพื่อแก้ไขเส้นทางสัมพัทธ์บนไดเร็กทอรีการทำงานและการให้ null เนื่องจากอาร์กิวเมนต์แรกดูแปลก ๆ
Nyerguds

1
ฉันขอขอบคุณคำแนะนำของคุณ แต่ฉันตั้งใจจะใช้ตัวช่วยนี้เฉพาะเมื่อฉันต้องการรวมเส้นทางฐานกับเส้นทางอื่นที่อาจสัมพันธ์กับเส้นทางฐานนั้นหรือสัมบูรณ์ นั่นเป็นเหตุผลที่ฉันต้องการใช้ลายเซ็นต่อไปนี้: GetAbsolutePath (String BasePath, String RelativeOrAbsolutePath) หากอาร์กิวเมนต์บางส่วนเป็นโมฆะจะมีการยกข้อยกเว้นขึ้นเพื่อตอกย้ำว่าทั้งคู่จำเป็นต้องใช้วิธีนี้ ขอขอบคุณอีกครั้ง :-)
Julio Nobre

2
ใช่มันสมเหตุสมผล ไม่ต้องกังวลที่จะแก้ไขสิ่งนี้เพื่อเล่นกลบางส่วน
Nyerguds

1

เป็นหัวข้อที่เก่ากว่าเล็กน้อย แต่อาจมีประโยชน์สำหรับใครบางคน ฉันได้แก้ไขปัญหาที่คล้ายกันแล้ว แต่ในกรณีของฉันเส้นทางไม่ได้อยู่ที่จุดเริ่มต้นของข้อความ

นี่คือทางออกของฉัน:

public static class StringExtension
{
    private const string parentSymbol = "..\\";
    private const string absoluteSymbol = ".\\";
    public static String AbsolutePath(this string relativePath)
    {
        string replacePath = AppDomain.CurrentDomain.BaseDirectory;
        int parentStart = relativePath.IndexOf(parentSymbol);
        int absoluteStart = relativePath.IndexOf(absoluteSymbol);
        if (parentStart >= 0)
        {
            int parentLength = 0;
            while (relativePath.Substring(parentStart + parentLength).Contains(parentSymbol))
            {
                replacePath = new DirectoryInfo(replacePath).Parent.FullName;
                parentLength = parentLength + parentSymbol.Length;
            };
            relativePath = relativePath.Replace(relativePath.Substring(parentStart, parentLength), string.Format("{0}\\", replacePath));
        }
        else if (absoluteStart >= 0)
        {
            relativePath = relativePath.Replace(".\\", replacePath);
        }
        return relativePath;
    }
}

ตัวอย่าง:

Data Source=.\Data\Data.sdf;Persist Security Info=False;
Data Source=..\..\bin\Debug\Data\Data.sdf;Persist Security Info=False;

1
อืม. คุณกำลังคิดค้นล้อใหม่ Path.GetFullPathแก้ไข. \ และ .. \ โดยอัตโนมัติ นอกจากนี้คุณกำลังเพิ่มAbsolutePathฟังก์ชันส่วนขยายในคลาส String โดยทั่วไป ... อาจจะมากเกินไป
Nyerguds

1
ฉันผิดหรือไม่ที่บอกว่า Path.GetFullPath ถือว่าไดเรกทอรีฐานเป็นไดเรกทอรีปัจจุบันของ AppDomain ของแอปพลิเคชัน ในกรณีนี้ Path.GetFullPath ไม่สามารถส่งคืนเส้นทางแบบเต็มจากไดเร็กทอรีอื่น อย่างไรก็ตามอัลกอริทึมต่อไปนี้จะคำนึงถึงสิ่งนี้ ... ฉันหมายความว่าคุณต้องเพิ่มพารามิเตอร์ทางเลือกอื่นซึ่งจะเป็นการแทนที่ CurrentDomainDirectory
ซามูเอล
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.