. net框架是否有任何方法来转换路径(例如。"C:\whatever.txt")转换为文件URI(例如:“文件:/ / / C: / whatever.txt”)?
这个系统。Uri类具有相反的情况(从文件Uri到绝对路径),但就我所能找到的转换为文件Uri而言,没有任何东西。
另外,这不是一个ASP。网络应用程序。
. net框架是否有任何方法来转换路径(例如。"C:\whatever.txt")转换为文件URI(例如:“文件:/ / / C: / whatever.txt”)?
这个系统。Uri类具有相反的情况(从文件Uri到绝对路径),但就我所能找到的转换为文件Uri而言,没有任何东西。
另外,这不是一个ASP。网络应用程序。
当前回答
Unfortunately @poizan42 answer does not take into account the fact that we live in a Unicode world and it's too restrictive according to RFC3986. The accepted answer of @pierre-arnaud and @jaredpar relies on the System.Uri constructor that has to take care for too many components of the Uri to be able to manage the variability of file names and it fails poorly on percent character and others cases. The other answers are simplicistics or simply unuseful. The best one would have been @is4, but after posting the first version of this post I tested it together in the test case I wrote for mine and it fails on many Unicode characters.
在我的例子中,我开始研究@poizan42代码和各种答案注释什么是有效的,什么是无效的,所以我采取了稍微不同的方法。
首先,我认为输入字符串是一个有效的文件路径,所以我在测试中使用所有有效的unicode字符和代理对以编程方式创建了路径。有了这个,我验证了至少Path.GetInvalidFileNameChars()似乎至少在Windows中返回正确的集。 然后,我将这些路径传递给一个方法,该方法是根据路径的ABNF规则实现的,您可以在https://www.ietf.org/rfc/rfc3986.txt的第22页中找到该规则。
我比较了它的结果与什么UriBuilder生成,这是结果修复:
public static string FilePathToFileUrl(string path)
{
return new UriBuilder("file",string.Empty)
{
Path = path
.Replace("%",$"%{(int)'%':X2}")
.Replace("[",$"%{(int)'[':X2}")
.Replace("]",$"%{(int)']':X2}"),
}
.Uri
.AbsoluteUri;
}
这是完全未优化的,并执行三次替换,所以请随意将其转换为Span或StringBuilder。
其他回答
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的长度,因此我首先获取长度,然后分配缓冲区。
一些非常有趣的观察是,当“\\device\path”被正确地转换为“file://device/path”时,特别是“\\localhost\path”被转换为“file:///path”。
WinApi函数设法对特殊字符进行编码,但不像Uri构造函数那样对特定于unicode的字符进行编码。在这种情况下,AbsoluteUri包含正确编码的URL,而OriginalString可用于保留Unicode字符。
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
输出:文件:/ / / D: /开发/ ~ AppFolder /丙氨酸/ 1. gif
变通办法很简单。只需使用Uri(). tostring()方法,然后使用百分比编码的空格(如果有的话)。
string path = new Uri("C:\my exampleㄓ.txt").ToString().Replace(" ", "%20");
正确返回文件:///C:/my%20exampleㄓ.txt
Unfortunately @poizan42 answer does not take into account the fact that we live in a Unicode world and it's too restrictive according to RFC3986. The accepted answer of @pierre-arnaud and @jaredpar relies on the System.Uri constructor that has to take care for too many components of the Uri to be able to manage the variability of file names and it fails poorly on percent character and others cases. The other answers are simplicistics or simply unuseful. The best one would have been @is4, but after posting the first version of this post I tested it together in the test case I wrote for mine and it fails on many Unicode characters.
在我的例子中,我开始研究@poizan42代码和各种答案注释什么是有效的,什么是无效的,所以我采取了稍微不同的方法。
首先,我认为输入字符串是一个有效的文件路径,所以我在测试中使用所有有效的unicode字符和代理对以编程方式创建了路径。有了这个,我验证了至少Path.GetInvalidFileNameChars()似乎至少在Windows中返回正确的集。 然后,我将这些路径传递给一个方法,该方法是根据路径的ABNF规则实现的,您可以在https://www.ietf.org/rfc/rfc3986.txt的第22页中找到该规则。
我比较了它的结果与什么UriBuilder生成,这是结果修复:
public static string FilePathToFileUrl(string path)
{
return new UriBuilder("file",string.Empty)
{
Path = path
.Replace("%",$"%{(int)'%':X2}")
.Replace("[",$"%{(int)'[':X2}")
.Replace("]",$"%{(int)']':X2}"),
}
.Uri
.AbsoluteUri;
}
这是完全未优化的,并执行三次替换,所以请随意将其转换为Span或StringBuilder。
至少在。net 4.5+中你还可以做到:
var uri = new System.Uri("C:\\foo", UriKind.Absolute);