2009-10-27 8 views
18

पथ.कॉम्बिन() के विपरीत की गणना करने का कोई विश्वसनीय तरीका है?कुछ रूट के सापेक्ष पथ की गणना करना- पथ के विपरीत। कोम्बिन

पथ। कॉम्बिन ("सी: \ फ़ोल्डर", "उपनिर्देशिका \ something.txt") कुछ "c: \ folder \ subdirectory \ something.text" जैसे कुछ वापस कर सकता है। मैं जो चाहता हूं वह उलटा है, एक ऐसा फ़ंक्शन जहां पथ। गेटरेलेटिव यूआरएल ("सी: \ फ़ोल्डर", "सी: \ फ़ोल्डर \ subdirectory \ something.text") कुछ उपनिर्देशिका \ something.txt की तरह कुछ वापस करेगा।

एक समाधान स्ट्रिंग तुलना करना और जड़ों को ट्रिम करना है, लेकिन यह तब काम नहीं करेगा जब एक ही पथ अलग-अलग तरीकों से व्यक्त किया जाता है (पथ अभिव्यक्ति में ".." या "~ 1" का उपयोग)।

+0

क्या एक ही मशीन पर पथ हैं? यदि सामान्यीकरण सामान्य नहीं हो सकता है। Http://stackoverflow.com/questions/684684/normalize-file-path-with-winapi/684787 –

+0

अच्छा बिंदु यह एक कठिन परिदृश्य है जब एक पथ नेटवर्क मैप ड्राइव होता है और दूसरा एक ही ड्राइव पर स्थानीय फ़ाइल पथ होता है । सौभाग्य से यह एक परिदृश्य नहीं है जिसके साथ मुझे निपटना होगा। –

+0

रिक स्ट्राल के पास उरी कक्षा का उपयोग करने का एक समाधान है: http://west-wind.com/weblog/posts/857279.aspx –

उत्तर

17

ठीक है तो मेरे मामले में मेरे पास कुछ कठिन किनारे के मामले नहीं हैं (पूर्णपाथ और सापेक्षपाथ मिश्रण नेटवर्क मानचित्र स्थान, सुपर लंबे फ़ाइल नाम)। मैं क्या कर रहा था

public class PathUtil 
{ 
    static public string NormalizeFilepath(string filepath) 
    { 
     string result = System.IO.Path.GetFullPath(filepath).ToLowerInvariant(); 

     result = result.TrimEnd(new [] { '\\' }); 

     return result; 
    } 

    public static string GetRelativePath(string rootPath, string fullPath) 
    { 
     rootPath = NormalizeFilepath(rootPath); 
     fullPath = NormalizeFilepath(fullPath); 

     if (!fullPath.StartsWith(rootPath)) 
      throw new Exception("Could not find rootPath in fullPath when calculating relative path."); 

     return "." + fullPath.Substring(rootPath.Length); 
    } 
} 

यह वर्ग अच्छी तरह से काम करता प्रतीत होता है। कम से कम, यह इन NUnit परीक्षण गुजरता है:

[TestFixture] 
public class PathUtilTest 
{ 
    [Test] 
    public void TestDifferencesInCapitolizationDontMatter() 
    { 
     string format1 = PathUtil.NormalizeFilepath("c:\\windows\\system32"); 
     string format2 = PathUtil.NormalizeFilepath("c:\\WindowS\\System32"); 

     Assert.AreEqual(format1, format2); 
    } 

    [Test] 
    public void TestDifferencesDueToBackstepsDontMatter() 
    { 
     string format1 = PathUtil.NormalizeFilepath("c:\\windows\\system32"); 
     string format2 = PathUtil.NormalizeFilepath("c:\\Program Files\\..\\Windows\\System32"); 

     Assert.AreEqual(format1, format2); 
    } 

    [Test] 
    public void TestDifferencesInFinalSlashDontMatter() 
    { 
     string format1 = PathUtil.NormalizeFilepath("c:\\windows\\system32"); 
     string format2 = PathUtil.NormalizeFilepath("c:\\windows\\system32\\"); 

     Console.WriteLine(format1); 
     Console.WriteLine(format2); 

     Assert.AreEqual(format1, format2); 
    } 

    [Test] 
    public void TestCanCalculateRelativePath() 
    { 
     string rootPath = "c:\\windows"; 
     string fullPath = "c:\\windows\\system32\\wininet.dll"; 
     string expectedResult = ".\\system32\\wininet.dll"; 

     string result = PathUtil.GetRelativePath(rootPath, fullPath); 

     Assert.AreEqual(expectedResult, result); 
    } 

    [Test] 
    public void TestThrowsExceptionIfRootDoesntMatchFullPath() 
    { 
     string rootPath = "c:\\windows"; 
     string fullPath = "c:\\program files\\Internet Explorer\\iexplore.exe"; 

     try 
     { 
      PathUtil.GetRelativePath(rootPath, fullPath); 
     } 
     catch (Exception) 
     { 
      return; 
     } 

     Assert.Fail("Exception expected"); 
    } 
} 

परीक्षण मामलों मौजूदा .. इन फ़ाइलों अधिकांश विंडो स्थापित करता है लेकिन आपका माइलेज भिन्न हो सकते हैं आम हैं कुछ फ़ाइलों पर निर्भर हैं।

0

पथ का प्रयास करें .GetFullPath पहले, और उसके बाद स्ट्रिंग तुलना।

5

मैंने लंबे फ़ाइल पथों के साथ ऐसा करने का एक तरीका खोजने का प्रयास किया लेकिन मुझे संतोषजनक परिणाम नहीं मिल रहे हैं क्योंकि आप Win32 में पथों के कैननिकलाइजेशन को खो देते हैं जब आप लंबे पथ संस्करणों का उपयोग करते हैं मानक फ़ाइल सिस्टम कॉल। तो यह समाधान आवश्यक रूप से 260 वर्णों से अधिक चीजों के साथ काम नहीं करता है, लेकिन यह प्रबंधित कोड और मस्तिष्क मृत अन्यथा सरल है।

string path1 = @"c:\folder\subdirectory\something.text"; 
string path2 = @"c:\folder\foo\..\something.text"; 
Uri value = new Uri(path1); 
Uri value2 = new Uri(path2); 
Uri result = value.MakeRelativeUri(value2); 
Console.WriteLine(result.OriginalString); 

कौन सा

../something.text 

देता है अब पथ के लिए 8.3 नाम (लघु नाम) एक अलग बात है। यह मेरी समझ है कि उन पथों को फाइल सिस्टम में संग्रहीत किया जाता है और आपको उन्हें प्राप्त करने के लिए Win32 का उपयोग करना होगा। इसके अलावा उन्हें अक्षम किया जा सकता है इसलिए कोई गारंटी नहीं है कि वे वहां हैं। एक छोटे से पथ से लंबा रास्ता प्राप्त करने के लिए आप Kernel32.dll में GetLongPathName को कॉल करते हैं। इसका मतलब यह भी है कि फाइल मौजूद है।

यदि आप ऐसा करना चाहते हैं तो यह साइट आपका मित्र है। GetLongPathName

+0

ओह बेबी, जो पथ की समस्याओं से प्यार नहीं करता है? मुझे लगता है कि यूरी क्लास को इंगित करना वैसे भी सबसे अच्छा जवाब है, धन्यवाद। – anhoppe

3

मैंने इसे निम्नलिखित फ़ंक्शन के साथ किया है। पहला पैरामीटर वह निर्देशिका है जिसे हम देख रहे थे, दूसरा पैरामीटर गंतव्य पथ है। दोनों पथ सापेक्ष हो सकते हैं। समारोह अनुकूलित नहीं है लेकिन यह काम करता है।

private string _GetRelativePath(string fromPath, string toPath) 
{ 
    string fromFull = Path.Combine(Environment.CurrentDirectory, fromPath); 
    string toFull = Path.Combine(Environment.CurrentDirectory, toPath); 

    List<string> fromParts = new List<string> 
     fromFull.Split(Path.DirectorySeparatorChar)); 
    List<string> toParts = 
     new List<string>(toFull.Split(Path.DirectorySeparatorChar)); 

    fromParts.RemoveAll(string.IsNullOrEmpty); 
    toParts.RemoveAll(string.IsNullOrEmpty); 

    // Remove all the same parts in front 
    bool areRelative = false; 
    while (fromParts.Count > 0 && toParts.Count > 0 && 
     StringComparer.OrdinalIgnoreCase.Compare(fromParts[0], toParts[0]) == 0) 
    { 
     fromParts.RemoveAt(0); 
     toParts.RemoveAt(0); 

     areRelative = true; 
    } 

    if (!areRelative) 
     return toPath; 

    // Number of remaining fromParts is number of parent dirs 
    StringBuilder ret = new StringBuilder(); 

    for (int i = 0; i < fromParts.Count; i++) 
    { 
     if (ret.Length > 0) 
       ret.Append(Path.DirectorySeparatorChar); 

     ret.Append(".."); 
    } 

    // And the remainder of toParts 
    foreach (string part in toParts) 
    { 
     if (ret.Length > 0) 
       ret.Append(Path.DirectorySeparatorChar); 

     ret.Append(part); 
    } 

    return ret.ToString(); 
} 
संबंधित मुद्दे