Path.Combine的url?
Path.Combine很方便,但在.NET框架中有没有类似的function?
我正在寻找这样的语法:
Url.Combine("http://MyUrl.com/", "/Images/Image.jpg")
这将返回:
"Images/Image.jpg"
Uri
有一个构造函数,应该为你做这个: new Uri(Uri baseUri, string relativeUri)
这是一个例子:
Uri baseUri = new Uri("http://www.contoso.com"); Uri myUri = new Uri(baseUri, "catalog/shownew.htm");
您使用Uri.TryCreate( ... )
:
Uri result = null; if (Uri.TryCreate(new Uri("http://msdn.microsoft.com/en-us/library/"), "/en-us/library/system.uri.trycreate.aspx", out result)) { Console.WriteLine(result); }
将返回:
http://msdn.microsoft.com/en-us/library/system.uri.trycreate.aspx
这可能是一个适当简单的解决scheme:
public static string Combine(string uri1, string uri2) { uri1 = uri1.TrimEnd('/'); uri2 = uri2.TrimStart('/'); return string.Format("{0}/{1}", uri1, uri2); }
这里已经有一些很好的答案。 基于mdsharpe的build议,这里有一个扩展方法,当你想处理Uri实例时可以很容易地使用:
using System; using System.Linq; public static class UriExtensions { public static Uri Append(this Uri uri, params string[] paths) { return new Uri(paths.Aggregate(uri.AbsoluteUri, (current, path) => string.Format("{0}/{1}", current.TrimEnd('/'), path.TrimStart('/')))); } }
和用法示例:
var url = new Uri("http://example.com/subpath/").Append("/part1/", "part2").AbsoluteUri;
这个问题得到了一些伟大的,高度投票的答案!
Ryan Cook的答案与我之后的答案很接近,可能更适合于其他开发者。 但是,它将http://添加到string的开头,一般来说,它的格式要比我以前多一些。
另外,对于我的用例来说,解决相对path并不重要。
mdsharp的答案也包含了一个好主意的种子,尽pipe实际的实现需要更多的细节来完成。 这是一个试图充实(我正在使用这个在生产中):
C#
public string UrlCombine(string url1, string url2) { if (url1.Length == 0) { return url2; } if (url2.Length == 0) { return url1; } url1 = url1.TrimEnd('/', '\\'); url2 = url2.TrimStart('/', '\\'); return string.Format("{0}/{1}", url1, url2); }
VB.Net
Public Function UrlCombine(ByVal url1 As String, ByVal url2 As String) As String If url1.Length = 0 Then Return url2 End If If url2.Length = 0 Then Return url1 End If url1 = url1.TrimEnd("/"c, "\"c) url2 = url2.TrimStart("/"c, "\"c) Return String.Format("{0}/{1}", url1, url2) End Function
这段代码通过了下面的testing,这恰好在VB中:
<TestMethod()> Public Sub UrlCombineTest() Dim target As StringHelpers = New StringHelpers() Assert.IsTrue(target.UrlCombine("test1", "test2") = "test1/test2") Assert.IsTrue(target.UrlCombine("test1/", "test2") = "test1/test2") Assert.IsTrue(target.UrlCombine("test1", "/test2") = "test1/test2") Assert.IsTrue(target.UrlCombine("test1/", "/test2") = "test1/test2") Assert.IsTrue(target.UrlCombine("/test1/", "/test2/") = "/test1/test2/") Assert.IsTrue(target.UrlCombine("", "/test2/") = "/test2/") Assert.IsTrue(target.UrlCombine("/test1/", "") = "/test1/") End Sub
根据您提供的示例url ,我将假设您想要合并与您的网站相关的url。
基于这个假设,我将提出这个解决scheme作为对你的问题的最恰当的回应:“Path.Combine是方便的,在URL的框架中是否有类似的function ?
由于那里在URL的框架中有一个类似的function ,我build议正确的是:“VirtualPathUtility.Combine”方法。 以下是MSDN参考链接: VirtualPathUtility.Combine方法
有一个警告:我相信这只适用于网站相对于您的网站(也就是说,你不能用它来产生链接到另一个网站。例如, var url = VirtualPathUtility.Combine("www.google.com", "accounts/widgets");
)。
Path.Combine不适合我,因为可以有像“|” 在QueryString参数,因此Url,这将导致一个ArgumentException。
我首先尝试了新的Uri(Uri baseUri,string relativeUri)方法,由于Uri的原因,我失败了,如http://www.mediawiki.org/wiki/Special:SpecialPages
:
new Uri(new Uri("http://www.mediawiki.org/wiki/"), "Special:SpecialPages")
将会导致Special:SpecialPages,因为Special之后的冒号表示scheme。
所以我最终不得不采取mdsharpe / Brian MacKays的路线,并进一步开发了多个uri部分:
public static string CombineUri(params string[] uriParts) { string uri = string.Empty; if (uriParts != null && uriParts.Count() > 0) { char[] trims = new char[] { '\\', '/' }; uri = (uriParts[0] ?? string.Empty).TrimEnd(trims); for (int i = 1; i < uriParts.Count(); i++) { uri = string.Format("{0}/{1}", uri.TrimEnd(trims), (uriParts[i] ?? string.Empty).TrimStart(trims)); } } return uri; }
用法: CombineUri("http://www.mediawiki.org/", "wiki", "Special:SpecialPages")
Path.Combine("Http://MyUrl.com/", "/Images/Image.jpg").Replace("\\", "/")
我只是把小的扩展方法放在一起
public static string UriCombine (this string val, string append) { if (String.IsNullOrEmpty(val)) return append; if (String.IsNullOrEmpty(append)) return val; return val.TrimEnd('/') + "/" + append.TrimStart('/'); }
可以这样使用:
"www.example.com/".UriCombine("/images").UriCombine("first.jpeg");
举个例子,瑞安,结束与该function的链接。 做得好。
一个build议Brian:如果你把这个代码包装在一个函数中,你可能想要在TryCreate调用之前使用UriBuilder来包装基本的URL。
否则,基本URL必须包含该scheme(其中UriBuilder将采用http://)。 只是一个想法:
public string CombineUrl(string baseUrl, string relativeUrl) { UriBuilder baseUri = new UriBuilder(baseUrl); Uri newUri; if (Uri.TryCreate(baseUri.Uri, relativeUrl, out newUri)) return newUri.ToString(); else throw new ArgumentException("Unable to combine specified url values"); }
结合Url的多个部分可能有点棘手。 您可以使用2参数构造函数Uri(baseUri, relativeUri)
,也可以使用Uri.TryCreate()
实用程序函数。 无论是哪种情况,您最终都会返回不正确的结果,因为这些方法会继续截断第一个参数baseUri
的相关部分,即从http://google.com/some/thing
到http://google.com
为了能够将多个部分组合成最终的url,可以复制下面的两个函数:
public static string Combine(params string[] parts) { if (parts == null || parts.Length == 0) return string.Empty; var urlBuilder = new StringBuilder(); foreach (var part in parts) { var tempUrl = tryCreateRelativeOrAbsolute(part); urlBuilder.Append(tempUrl); } return VirtualPathUtility.RemoveTrailingSlash(urlBuilder.ToString()); } private static string tryCreateRelativeOrAbsolute(string s) { System.Uri uri; System.Uri.TryCreate(s, UriKind.RelativeOrAbsolute, out uri); string tempUrl = VirtualPathUtility.AppendTrailingSlash(uri.ToString()); return tempUrl; }
用unit testing来演示使用的完整代码可以在https://uricombine.codeplex.com/SourceControl/latest#UriCombine/Uri.csfind。;
我有unit testing涵盖3个最常见的情况:
我知道这已被回答,但一个简单的方法来结合他们,并确保它总是正确的是..
string.Format("{0}/{1}", Url1.Trim('/'), Url2);
这个答案可能会在上面的所有答案中都丢失,但是我发现UriBuilder
对于这样的事情非常有效。
UriBuilder urlb = new UriBuilder("http", _serverAddress, _webPort, _filePath); Uri url = urlb.Uri; return url.AbsoluteUri;
有关更多构造函数和文档,请参阅UriBuilder类 – MSDN 。
以下是Microsoft的(OfficeDev PnP)方法UrlUtility.Combine :
const char PATH_DELIMITER = '/'; /// <summary> /// Combines a path and a relative path. /// </summary> /// <param name="path"></param> /// <param name="relative"></param> /// <returns></returns> public static string Combine(string path, string relative) { if(relative == null) relative = String.Empty; if(path == null) path = String.Empty; if(relative.Length == 0 && path.Length == 0) return String.Empty; if(relative.Length == 0) return path; if(path.Length == 0) return relative; path = path.Replace('\\', PATH_DELIMITER); relative = relative.Replace('\\', PATH_DELIMITER); return path.TrimEnd(PATH_DELIMITER) + PATH_DELIMITER + relative.TrimStart(PATH_DELIMITER); }
来源: GitHub
我的通用解决scheme
public static string Combine(params string[] uriParts) { string uri = string.Empty; if (uriParts != null && uriParts.Any()) { char[] trims = new char[] { '\\', '/' }; uri = (uriParts[0] ?? string.Empty).TrimEnd(trims); for (int i = 1; i < uriParts.Length; i++) { uri = string.Format("{0}/{1}", uri.TrimEnd(trims), (uriParts[i] ?? string.Empty).TrimStart(trims)); } } return uri; }
我知道我晚了,但我创造了这个function,这将使您的生活更轻松
/// <summary> /// the ultimate Path combiner of all time /// </summary> /// <param name="IsURL"> /// true - if the paths are internet urls,false - if the paths are local urls,this is very important as this will be used to decide which separator will be used /// </param> /// <param name="IsRelative">just adds the separator at the beginning</param> /// <param name="IsFixInternal">fix the paths from within (by removing duplicate separators and correcting the separators)</param> /// <param name="parts">the paths to combine</param> /// <returns>the combined path</returns> public static string PathCombine(bool IsURL , bool IsRelative , bool IsFixInternal , params string[] parts) { if (parts == null || parts.Length == 0) return string.Empty; char separator = IsURL ? '/' : '\\'; if (parts.Length == 1 && IsFixInternal) { string validsingle; if (IsURL) { validsingle = parts[0].Replace('\\' , '/'); } else { validsingle = parts[0].Replace('/' , '\\'); } validsingle = validsingle.Trim(separator); return (IsRelative ? separator.ToString() : string.Empty) + validsingle; } string final = parts .Aggregate ( (string first , string second) => { string validfirst; string validsecond; if (IsURL) { validfirst = first.Replace('\\' , '/'); validsecond = second.Replace('\\' , '/'); } else { validfirst = first.Replace('/' , '\\'); validsecond = second.Replace('/' , '\\'); } var prefix = string.Empty; if (IsFixInternal) { if (IsURL) { if (validfirst.Contains("://")) { var tofix = validfirst.Substring(validfirst.IndexOf("://") + 3); prefix = validfirst.Replace(tofix , string.Empty).TrimStart(separator); var tofixlist = tofix.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries); validfirst = separator + string.Join(separator.ToString() , tofixlist); } else { var firstlist = validfirst.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries); validfirst = string.Join(separator.ToString() , firstlist); } var secondlist = validsecond.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries); validsecond = string.Join(separator.ToString() , secondlist); } else { var firstlist = validfirst.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries); var secondlist = validsecond.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries); validfirst = string.Join(separator.ToString() , firstlist); validsecond = string.Join(separator.ToString() , secondlist); } } return prefix + validfirst.Trim(separator) + separator + validsecond.Trim(separator); } ); return (IsRelative ? separator.ToString() : string.Empty) + final; }
它适用于URL和普通path
用法:
//fixes internal paths Console.WriteLine(PathCombine(true , true , true , @"\/\/folder 1\/\/\/\\/\folder2\///folder3\\/" , @"/\somefile.ext\/\//\")); //result : /folder 1/folder2/folder3/somefile.ext //doesn't fix internal paths Console.WriteLine(PathCombine(true , true , false , @"\/\/folder 1\/\/\/\\/\folder2\///folder3\\/" , @"/\somefile.ext\/\//\")); //result : /folder 1//////////folder2////folder3/somefile.ext //don't worry about url prefixes when fixing internal paths Console.WriteLine(PathCombine(true , false , true , @"/\/\/https:/\/\/\lul.com\/\/\/\\/\folder2\///folder3\\/" , @"/\somefile.ext\/\//\")); //result : https://lul.com/folder2/folder3/somefile.ext Console.WriteLine(PathCombine(false , true , true , @"../../../\\..\...\./../somepath" , @"anotherpath")); //result : \..\..\..\..\...\.\..\somepath\anotherpath
我知道这个问题很好的回答,但是我觉得这个有用,因为它具有以下特点
- 抛出空或空白
- 更接近模拟
System.Io.Path
静态类 - 为多个Url段获取
params
参数
注意:类名Url可以改变,因为有一个系统类System.Security.Policy.Url
类
public static class Url { private static string InternalCombine(string source, string dest) { // If the source is null or white space retune the dest only if (string.IsNullOrWhiteSpace(source)) { throw new ArgumentException("Cannot be null or white space", "source"); // throw new ArgumentException("Cannot be null or white space", nameof(source)); // c# 6.0 Nameof Expression } if (string.IsNullOrWhiteSpace(dest)) { throw new ArgumentException("Cannot be null or white space", "dest"); // throw new ArgumentException("Cannot be null or white space", nameof(dest)); // c# 6.0 Nameof Expression } source = source.TrimEnd('/', '\\'); dest = dest.TrimStart('/', '\\'); return string.Format("{0}/{1}", source, dest); // return $"{source}/{dest}"; // c# 6.0 string interpolation } public static string Combine(string source, params string[] args) { return args.Aggregate(source, InternalCombine); } }
结果
Url.Combine("test1", "test2"); Url.Combine("test1//", "test2"); Url.Combine("test1", "/test2"); // Result = test1/test2 Url.Combine(@"test1\/\/\/", @"\/\/\\\\\//test2", @"\/\/\\\\\//test3\") ; // Result = test1/test2/test3 Url.Combine("/test1/", "/test2/", null); Url.Combine("", "/test2/"); Url.Combine("/test1/", null); // Throws an ArgumentException
这个怎么样?
public static class WebPath { public static string Combine(params string[] args) { var prefixAdjusted = args.Select(x => x.StartsWith("/") && !x.StartsWith("http") ? x.Substring(1) : x); return string.Join("/", prefixAdjusted); } }
这是我的方法,我也将使用它
public static string UrlCombine(string part1, string part2) { string newPart1 = string.Empty; string newPart2 = string.Empty; string seprator = "/"; // if either part1 or part 2 is empty, // we don't need to combine with seprator if (string.IsNullOrEmpty(part1) || string.IsNullOrEmpty(part2)) { seprator = string.Empty; } // if part1 is not empty // remove '/' at last if (!string.IsNullOrEmpty(part1)) { newPart1 = part1.TrimEnd('/'); } // if part2 is not empty // remove '/' at first if (!string.IsNullOrEmpty(part2)) { newPart2 = part2.TrimStart('/'); } // now finally combine return string.Format("{0}{1}{2}", newPart1, seprator, newPart2); }
private Uri UriCombine(string path1, string path2, string path3 = "", string path4 = "") { string path = System.IO.Path.Combine(path1, path2.TrimStart('\\', '/'), path3.TrimStart('\\', '/'), path4.TrimStart('\\', '/')); string url = path.Replace('\\','/'); return new Uri(url); }
具有完全像Path.Combine一样的好处
更多的build议…我已经综合了以上所有:
public static string UrlPathCombine(string path1, string path2) { path1 = path1.TrimEnd('/') + "/"; path2 = path2.TrimStart('/'); return Path.Combine(path1, path2) .Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); } [TestMethod] public void TestUrl() { const string P1 = "http://msdn.microsoft.com/slash/library//"; Assert.AreEqual("http://msdn.microsoft.com/slash/library/site.aspx", UrlPathCombine(P1, "//site.aspx")); var path = UrlPathCombine("Http://MyUrl.com/", "Images/Image.jpg"); Assert.AreEqual( "Images/Image.jpg", path); }
那么,我只是连接两个string,并使用正则expression式来执行清理部分。
public class UriTool { public static Uri Join(string path1, string path2) { string url = path1 + "/" + path2; url = Regex.Replace(url, "(?<!http:)/{2,}", "/"); return new Uri(url); } }
所以,你可以这样使用:
string path1 = "http://someaddress.com/something/"; string path2 = "/another/address.html"; Uri joinedUri = UriTool.Join(path1, path2); // joinedUri.ToString() returns "http://someaddress.com/something/another/address.html"
希望对某人有用!
我用这个代码来解决这个问题:
string[] brokenBaseUrl = Context.Url.TrimEnd('/').Split('/'); string[] brokenRootFolderPath = RootFolderPath.Split('/'); for (int x = 0; x < brokenRootFolderPath.Length; x++) { //if url doesn't already contain member, append it to the end of the string with / in front if (!brokenBaseUrl.Contains(brokenRootFolderPath[x])) { if (x == 0) { RootLocationUrl = Context.Url.TrimEnd('/'); } else { RootLocationUrl += String.Format("/{0}", brokenRootFolderPath[x]); } } }
将URL与URI结合起来的规则
为了避免奇怪的行为,有一条规则可以遵循:
- path(目录)必须以'/'结尾。 如果path没有以“/”结尾,最后一个部分就像文件名一样对待,当试图与下一个url部分结合时,它会被连接在一起。
- 有一个例外:基地址(无目录信息)不需要以'/'结尾
- path部分不能以'/'开始,如果以'/'开始,则每个存在的来自URL的相关信息都会被删除…添加string。空的部分path也会从URL中删除相对目录!
如果您遵循上述规则,则可以将URL与下面的代码组合在一起。 根据你的情况,你可以添加多个“目录”部分到url…
var pathParts = new string[] { destinationBaseUrl, destinationFolderUrl, fileName }; var destination = pathParts.Aggregate((left, right) => { if (string.IsNullOrWhiteSpace(right)) return left; return new Uri(new Uri(left), right).ToString(); });
这两个工作
Uri final = new Uri(Regex.Replace(baseUrl + "/" + relativePath, "(?<!http:)/{2,}", "/"));
要么
Uri final =new Uri(string.Format("{0}/{1}", baseUrl.ToString().TrimEnd('/'), relativePath.ToString().TrimStart('/')));
即
如果
baseUrl =“ http://tesrurl.test.com/Int18 ”
和
relativePath =“To_Folder”
输出= http://tesrurl.test.com/Int18/To_Folder
下面的代码会出现一些错误
// if you use below code, some issues will be there in final uri Uri final= new Uri(baseUrl ,relativePath );
一个简单的衬垫:
public static string Combine(this string uri1, string uri2) => $"{uri1.TrimEnd('/')}/{uri2.TrimStart('/')}";
受@Matt Sharpe的回答启发。
我必须指出,Path.Combine似乎也适用于.NET4
我还没有使用下面的代码,但在我的互联网旅行中发现它解决了一个URL组合问题 – 希望它是一个简洁(和成功!)的答案:
VirtualPathUtility.Combine