फ़ाइल पथ को एक फ़ाइल URI में कनवर्ट करें?


201

क्या .NET फ्रेमवर्क में किसी पथ (जैसे "C:\whatever.txt") को फ़ाइल URI (उदा "file:///C:/whatever.txt") में परिवर्तित करने की कोई विधियाँ हैं ?

System.Uri वर्ग रिवर्स (एक फ़ाइल यूआरआई निरपेक्ष पथ तक) है, लेकिन कुछ भी नहीं है जहाँ तक मैं एक फ़ाइल यूआरआई को परिवर्तित करने के लिए मिल सकता है के रूप में।

इसके अलावा, यह है नहीं ASP.NET अनुप्रयोग।

जवाबों:


291

System.Uriनिर्माता पूर्ण फ़ाइल पथ पार्स और उन्हें यूआरआई शैली रास्तों में बदल जाने की क्षमता है। तो आप बस निम्नलिखित कर सकते हैं:

var uri = new System.Uri("c:\\foo");
var converted = uri.AbsoluteUri;

78
var path = new Uri("file:///C:/whatever.txt").LocalPath;एक Uri को एक स्थानीय फ़ाइलपाथ में बदल देता है जो किसी को भी इसकी आवश्यकता होती है।
पॉन्डिडम

2
नोट के रूप में। उरी के इस तरह के वीएस आउटपुट और आर # यूनिट परीक्षण आउटपुट पर सत्र विंडो में क्लिक करने योग्य है
एल्फेग

7
यह दुर्भाग्य से सही नहीं है। उदाहरण के लिए new Uri(@"C:\%51.txt").AbsoluteUriआपको "file:///C:/Q.txt"इसके बजाय"file:///C:/%2551.txt"
poizan42

2
इस रिक्त स्थान के साथ पथ, यानी साथ नहीं होगा काम: "C: \ test फ़ोल्डर \ whatever.txt"
Quad Coders

न ही यह उन रास्तों के साथ काम करेगा जिनमें एक # वर्ण है।
लुईस

42

कोई भी महसूस नहीं करता है कि System.Uriनिर्माणकर्ताओं में से कोई भी सही तरीके से कुछ संकेतों को नहीं दिखाता है।

new Uri(@"C:\%51.txt").AbsoluteUri;

इसके "file:///C:/Q.txt"बदले आपको देता है "file:///C:/%2551.txt"

न तो हटाए गए NOTEscape तर्क के मूल्यों से कोई फर्क पड़ता है, और UriKind को निर्दिष्ट करने से समान परिणाम भी मिलता है। UriBuilder के साथ कोशिश करना भी मदद नहीं करता है:

new UriBuilder() { Scheme = Uri.UriSchemeFile, Host = "", Path = @"C:\%51.txt" }.Uri.AbsoluteUri

"file:///C:/Q.txt"साथ ही यह वापसी करता है।

जहां तक ​​मैं बता सकता हूं कि रूपरेखा वास्तव में इसे सही तरीके से करने के किसी भी तरीके की कमी है।

हम इसे आगे की स्लैश के साथ बैकस्लैश की जगह ले कर कोशिश कर सकते हैं Uri.EscapeUriString- यानी - को पाथ कर सकते हैं

new Uri(Uri.EscapeUriString(filePath.Replace(Path.DirectorySeparatorChar, '/'))).AbsoluteUri

यह पहली बार में काम करने लगता है, लेकिन अगर आप इसे रास्ता देते हैं C:\a b.txtतो आप file:///C:/a%2520b.txtइसके बजाय समाप्त हो जाते हैं file:///C:/a%20b.txt- किसी तरह यह फैसला करता है कि कुछ दृश्यों को डिकोड किया जाना चाहिए, लेकिन दूसरों को नहीं। अब हम बस "file:///"अपने आप को उपसर्ग कर सकते हैं, हालांकि यह यूएनसी रास्तों को ध्यान में रखने में विफल रहता है \\remote\share\foo.txt- जैसा कि आमतौर पर विंडोज पर स्वीकार किया जाता है, उन्हें फॉर्म के छद्म-यूआरएल में बदलना है file://remote/share/foo.txt, इसलिए हमें इसे भी ध्यान में रखना चाहिए।

EscapeUriStringयह भी समस्या है कि यह '#'चरित्र से नहीं बचता है । इस बिंदु पर यह प्रतीत होता है कि हमारे पास कोई अन्य विकल्प नहीं है, लेकिन खरोंच से अपना खुद का तरीका बना रहा है। तो यह मेरा सुझाव है:

public static string FilePathToFileUrl(string filePath)
{
  StringBuilder uri = new StringBuilder();
  foreach (char v in filePath)
  {
    if ((v >= 'a' && v <= 'z') || (v >= 'A' && v <= 'Z') || (v >= '0' && v <= '9') ||
      v == '+' || v == '/' || v == ':' || v == '.' || v == '-' || v == '_' || v == '~' ||
      v > '\xFF')
    {
      uri.Append(v);
    }
    else if (v == Path.DirectorySeparatorChar || v == Path.AltDirectorySeparatorChar)
    {
      uri.Append('/');
    }
    else
    {
      uri.Append(String.Format("%{0:X2}", (int)v));
    }
  }
  if (uri.Length >= 2 && uri[0] == '/' && uri[1] == '/') // UNC path
    uri.Insert(0, "file:");
  else
    uri.Insert(0, "file:///");
  return uri.ToString();
}

यह जानबूझकर छोड़ देता है + और: जैसा कि लगता है कि यह आमतौर पर विंडोज पर किया जाता है। इंटरनेट एक्सप्लोरर के यूनिकोड वर्णों को यूआरकोड के रूप में समझने की जरूरत नहीं है, अगर वे एनकोडेड हैं तो फाइल यूआरएल में यूनिकोड वर्णों को नहीं समझ सकते।


क्या एक नगीना है जिसमें यह एक उदार लाइसेंस के साथ शामिल है? यह एक उचित तरीका है इसके लिए कोई उचित तरीका फ्रेमवर्क में मौजूद नहीं है और
कोपीपास्ट को

4
आप एमआईटी लाइसेंस की शर्तों के तहत ऊपर दिए गए कोड का उपयोग कर सकते हैं (मुझे विश्वास नहीं है कि कुछ भी कॉपीराइट योग्य होना चाहिए, लेकिन अब आपके पास एक स्पष्ट अनुदान है)
poizan42

9

ऊपर दिए गए समाधान लिनक्स पर काम नहीं करते हैं।

.NET कोर का उपयोग करना, new Uri("/home/foo/README.md")एक अपवाद में परिणाम निष्पादित करने का प्रयास करना :

Unhandled Exception: System.UriFormatException: Invalid URI: The format of the URI could not be determined.
   at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind)
   at System.Uri..ctor(String uriString)
   ...

आपको CLR कुछ संकेत देने की आवश्यकता है कि आपके पास किस प्रकार का URL है।

यह काम:

Uri fileUri = new Uri(new Uri("file://"), "home/foo/README.md");

... और स्ट्रिंग वापस आ गई fileUri.ToString()है"file:///home/foo/README.md"

यह विंडोज पर भी काम करता है।

new Uri(new Uri("file://"), @"C:\Users\foo\README.md").ToString()

... का उत्सर्जन करता है "file:///C:/Users/foo/README.md"


यदि आप जानते हैं कि मार्ग निरपेक्ष है तो आप उपयोग कर सकते हैंnew Uri("/path/to/file", UriKind.Absolute);
मिनीजैक

8

VB.NET:

Dim URI As New Uri("D:\Development\~AppFolder\Att\1.gif")

विभिन्न आउटपुट:

URI.AbsolutePath   ->  D:/Development/~AppFolder/Att/1.gif  
URI.AbsoluteUri    ->  file:///D:/Development/~AppFolder/Att/1.gif  
URI.OriginalString ->  D:\Development\~AppFolder\Att\1.gif  
URI.ToString       ->  file:///D:/Development/~AppFolder/Att/1.gif  
URI.LocalPath      ->  D:\Development\~AppFolder\Att\1.gif

एक लाइन:

New Uri("D:\Development\~AppFolder\Att\1.gif").AbsoluteUri

आउटपुट :file:///D:/Development/~AppFolder/Att/1.gif


2
AbsoluteUriयह एक सही है क्योंकि यह 20% के लिए भी रिक्त स्थान रखता है।
अक्टूबर को सुबह

मुझे विश्वास है कि यह उत्तर में वर्णित उन्हीं समस्याओं से ग्रस्त है जो विशेष चरित्र से निपटने की बात करती है
binki

4

कम से कम .NET 4.5+ में आप यह भी कर सकते हैं:

var uri = new System.Uri("C:\\foo", UriKind.Absolute);

1
क्या आपको UriFormatExceptionएक दिन होने का जोखिम नहीं है?
berezovskyi

यह या तो सही ढंग से काम नहीं करता है, new Uri(@"C:\%51.txt",UriKind.Absolute).AbsoluteUriरिटर्न "file:///C:/Q.txt"के बजाय"file:///C:/%2551.txt"
poizan42

2

बचाव के लिए UrlCreateFromPath ! ठीक है, पूरी तरह से नहीं, क्योंकि यह विस्तारित और UNC पथ स्वरूपों का समर्थन नहीं करता है, लेकिन इससे उबरना इतना कठिन नहीं है:

public static Uri FileUrlFromPath(string path)
{
    const string prefix = @"\\";
    const string extended = @"\\?\";
    const string extendedUnc = @"\\?\UNC\";
    const string device = @"\\.\";
    const StringComparison comp = StringComparison.Ordinal;

    if(path.StartsWith(extendedUnc, comp))
    {
        path = prefix+path.Substring(extendedUnc.Length);
    }else if(path.StartsWith(extended, comp))
    {
        path = prefix+path.Substring(extended.Length);
    }else if(path.StartsWith(device, comp))
    {
        path = prefix+path.Substring(device.Length);
    }

    int len = 1;
    var buffer = new StringBuilder(len);
    int result = UrlCreateFromPath(path, buffer, ref len, 0);
    if(len == 1) Marshal.ThrowExceptionForHR(result);

    buffer.EnsureCapacity(len);
    result = UrlCreateFromPath(path, buffer, ref len, 0);
    if(result == 1) throw new ArgumentException("Argument is not a valid path.", "path");
    Marshal.ThrowExceptionForHR(result);
    return new Uri(buffer.ToString());
}

[DllImport("shlwapi.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern int UrlCreateFromPath(string path, StringBuilder url, ref int urlLength, int reserved);

यदि पथ एक विशेष उपसर्ग के साथ शुरू होता है, तो यह हटा दिया जाता है। हालाँकि यह दस्तावेज़ीकरण इसका उल्लेख नहीं करता है, फ़ंक्शन बफ़र छोटा होने के बावजूद URL की लंबाई को आउटपुट करता है, इसलिए मैं पहले लंबाई प्राप्त करता हूं और फिर बफ़र आवंटित करता हूं।

मेरे पास कुछ बहुत ही रोचक अवलोकन यह है कि जब "\\ डिवाइस \ पथ" सही ढंग से "फ़ाइल: // डिवाइस / पथ" में बदल जाता है, विशेष रूप से "\\ लोकलहोस्ट" पथ "फ़ाइल: /// पथ" में बदल जाता है ।

WinApi फ़ंक्शन विशेष वर्णों को एनकोड करने में कामयाब रहा, लेकिन यूरीकोड-विशिष्ट वर्णों को उरी बाधा के विपरीत अनएकोडेड छोड़ देता है । उस स्थिति में, AbsoluteUri में ठीक से एन्कोडेड URL होता है, जबकि OriginalString का उपयोग यूनिकोड वर्णों को बनाए रखने के लिए किया जा सकता है।


0

वर्कअराउंड सरल है। बस उरी ()। ToString () विधि और प्रतिशत-सांकेतिक शब्दों में बदलना-रिक्त स्थान, यदि कोई हो, का उपयोग करें।

string path = new Uri("C:\my exampleㄓ.txt").ToString().Replace(" ", "%20");

ठीक से रिटर्न फाइल: /// C: / मेरा% 20example t .txt

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.