IT

경로. URL에 대해 결합하시겠습니까?

itgroup 2023. 5. 28. 20:34
반응형

경로. URL에 대해 결합하시겠습니까?

Path.Combine은 편리하지만 URL에 대한 .NET 프레임워크에도 비슷한 기능이 있습니까?

다음과 같은 구문을 찾고 있습니다.

Url.Combine("http://MyUrl.com/", "/Images/Image.jpg")

다음과 같이 반환됩니다.

"http://MyUrl.com/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의 일부를 절단할 수 있습니다.댓글 및 기타 답변을 참조하십시오.

이는 적합하게 간단한 해결책일 수 있습니다.

public static string Combine(string uri1, string uri2)
{
    uri1 = uri1.TrimEnd('/');
    uri2 = uri2.TrimStart('/');
    return string.Format("{0}/{1}", uri1, uri2);
}

여기에는 이미 몇 가지 훌륭한 답이 있습니다.mdssharp 제안을 기반으로 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;

그러면 http://example.com/subpath/part1/part2 이 생성됩니다.

Uris 대신 문자열로 작업하려면 다음과 같은 결과를 생성합니다. 필요에 맞게 조정하기만 하면 됩니다.

public string JoinUriSegments(string uri, params string[] segments)
{
    if (string.IsNullOrWhiteSpace(uri))
        return null;

    if (segments == null || segments.Length == 0)
        return uri;

    return segments.Aggregate(uri, (current, segment) => $"{current.TrimEnd('/')}/{segment.TrimStart('/')}");
}

var uri = JoinUriSegements("http://example.com/subpath/", "/part1/", "part2");

당신은 용자를 합니다.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

에 토드 메니어의 논평이 있는데 플룰은 다음을 포함합니다.Url.Combine.

자세한 정보:

Url.Combine은 기본적으로 경로입니다.URL에 대해 결합하여 부품 사이에 하나의 구분 문자만 표시합니다.

var url = Url.Combine(
    "http://MyUrl.com/",
    "/too/", "/many/", "/slashes/",
    "too", "few?",
    "x=1", "y=2"
// result: "http://www.MyUrl.com/too/many/slashes/too/few?x=1&y=2" 

Flurl을 가져옵니다.NuGet의 Http:

PM > 설치 - 패키지 플urlurlHttp

또는 HTTP 기능이 없는 독립 실행형 URL 작성기를 가져옵니다.

PM> 설치 - 패키지 플url

Ryan Cook의 답변은 제가 추구하는 것과 비슷하며 다른 개발자들에게 더 적합할 수도 있습니다.그러나 문자열의 시작 부분에 http://를 추가하고 일반적으로 제가 원하는 것보다 더 많은 형식을 제공합니다.

또한 사용 사례의 경우 상대 경로를 해결하는 것은 중요하지 않습니다.

Mdssharp의 답변에는 좋은 아이디어의 씨앗도 포함되어 있지만, 실제 구현을 완료하려면 몇 가지 세부 사항이 더 필요합니다.이는 이를 구체화하기 위한 시도입니다(그리고 저는 이를 프로덕션에 사용하고 있습니다).

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

이 코드는 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

QueryString 인수와 URL에 "|"과 같은 문자가 있을 수 있으므로 Path.Combine이 작동하지 않습니다. 이 경우 인수가 발생합니다.예외.

나는 처음에 새로운 것을 시도했습니다.Uri(Uri baseUri, string relativeUri) URI, URI와 같은 입니다.http://www.mediawiki.org/wiki/Special:SpecialPages:

new Uri(new Uri("http://www.mediawiki.org/wiki/"), "Special:SpecialPages")

특수 결과가 표시됩니다.Pages, 특수페 뒤에 에, 음콜론때문에다지이에.Special그것은 계획을 의미합니다.

그래서 결국 mdsshappe/Brian MacKays 경로를 선택해야 했고 여러 URI 파트와 함께 작업하기 위해 조금 더 개발했습니다.

public static string CombineUri(params string[] uriParts)
{
    string uri = string.Empty;
    if (uriParts != null && uriParts.Length > 0)
    {
        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;
}

용도:CombineUri("http://www.mediawiki.org/", "wiki", "Special:SpecialPages")

당신이 제공한 샘플 URL을 바탕으로, 당신이 당신의 사이트와 관련된 URL을 결합하기를 원한다고 가정합니다.

이러한 가정을 바탕으로 "경로"라는 질문에 대한 가장 적절한 답변으로 이 솔루션을 제안하겠습니다.콤바인은 편리한데, URL용 프레임워크에도 비슷한 기능이 있나요?"

URL 프레임워크에 유사한 기능이 있으므로 올바른 것은 "VirtualPathUtility"입니다.결합" 방법입니다.MSDN 참조 링크는 VirtualPathUtility입니다.결합 방법

한 가지 주의할 점이 있습니다.이것은 당신의 사이트와 관련된 URL에만 사용할 수 있다고 생각합니다. 즉, 다른 웹 사이트에 대한 링크를 생성하는 데 사용할 수 없습니다.를 들면, 들면를예,var url = VirtualPathUtility.Combine("www.google.com", "accounts/widgets");).

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");

이를 결합하여 항상 올바른 상태를 유지하는 쉬운 방법은 다음과 같습니다.

string.Format("{0}/{1}", Url1.Trim('/'), Url2);

재치있는 예, 라이언, 함수에 대한 링크로 마무리하겠습니다.잘 했어요.

한 가지 권장 사항 Brian: 이 코드를 함수로 래핑할 경우 TryCreate 호출 전에 UriBuilder를 사용하여 기본 URL을 래핑할 수 있습니다.

그렇지 않으면 기본 URL에 체계가 포함되어야 합니다(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");
}

이를 통해 원하는 만큼의 경로 세그먼트를 처리할 수 있는 유연성을 확보할 수 있습니다.

public static string UrlCombine(this string baseUrl, params string[] segments)
=> string.Join("/", new[] { baseUrl.TrimEnd('/') }.Concat(segments.Select(s => s.Trim('/'))));

URL의 여러 부분을 결합하는 것은 약간 까다로울 수 있습니다. 생성자 2-모수 생성자를 할 수 .Uri(baseUri, relativeUri)또는 사용할 수 있습니다.Uri.TryCreate()효용 함수

모두 첫 매개변수의 을 계속 할 수 . 이러한 방법은 첫 번째 매개변수에서 상대적인 부분을 계속 잘라내기 때문입니다.baseUri들어, 들어것비, 에서한슷를과 같은 http://google.com/some/thinghttp://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;
    }

사용법을 입증하기 위한 장치 테스트가 포함된 전체 코드는 https://uricombine.codeplex.com/SourceControl/latest#UriCombine/Uri.cs 에서 확인할 수 있습니다.

가장 흔한 세 가지 경우를 다루기 위한 단위 테스트가 있습니다.

여기에 이미지 설명 입력

다른 답변에서 발견된 바와 같이, 새로운 답변 중 하나입니다.Uri()또는TryCreate()틱을 할 수 있습니다.는 "URI", "URI"로 끝나야 ./이 그고친시필작없요습다니가로 시작하지 않아야 ./그렇지 않으면 기본 Url의 후행 부분을 제거합니다.

이것은 확장 방법으로 하는 것이 가장 좋다고 생각합니다.

public static Uri Append(this Uri uri, string relativePath)
{
    var baseUri = uri.AbsoluteUri.EndsWith('/') ? uri : new Uri(uri.AbsoluteUri + '/');
    var relative = relativePath.StartsWith('/') ? relativePath.Substring(1) : relativePath;
    return new Uri(baseUri, relative);
}

사용 방법:

var baseUri = new Uri("http://test.com/test/");
var combinedUri =  baseUri.Append("/Do/Something");

성능 면에서 이는 많은 구문 분석 및 검증을 수행하는 URI 클래스 때문에 필요한 것보다 더 많은 리소스를 소비합니다. 매우 거친 프로파일링(디버그)은 약 2초 만에 백만 개의 작업을 수행했습니다.이는 대부분의 시나리오에서 작동하지만, 보다 효율적으로 모든 것을 문자열로 처리하는 것이 좋습니다. 100만 번의 작업에 125밀리초가 소요됩니다.예.

public static string Append(this Uri uri, string relativePath)
{
    //avoid the use of Uri as it's not needed, and adds a bit of overhead.
    var absoluteUri = uri.AbsoluteUri; //a calculated property, better cache it
    var baseUri = absoluteUri.EndsWith('/') ? absoluteUri : absoluteUri + '/';
    var relative = relativePath.StartsWith('/') ? relativePath.Substring(1) : relativePath;
    return baseUri + relative;
}

또한 URI를 반환하려면 100만 번의 작업에 약 600밀리초가 소요됩니다.

public static Uri AppendUri(this Uri uri, string relativePath)
{
    //avoid the use of Uri as it's not needed, and adds a bit of overhead.
    var absoluteUri = uri.AbsoluteUri; //a calculated property, better cache it
    var baseUri = absoluteUri.EndsWith('/') ? absoluteUri : absoluteUri + '/';
    var relative = relativePath.StartsWith('/') ? relativePath.Substring(1) : relativePath;
    return new Uri(baseUri + relative);
}

이것이 도움이 되길 바랍니다.

찾았습니다UriBuilder이런 종류의 일에 정말 잘 작동했습니다.

UriBuilder urlb = new UriBuilder("http", _serverAddress, _webPort, _filePath);
Uri url = urlb.Uri;
return url.AbsoluteUri;

자세한 생성자 및 설명서는 UriBuilder Class - MSDN을 참조하십시오.

새로운 메소드를 만들거나 새 라이브러리를 참조하지 않고 단순히 경로의 일부를 결합하거나 URI 값을 구성하여 문자열로 변환하려는 사용자를 위해...

string urlToImage = String.Join("/", "websiteUrl", "folder1", "folder2", "folder3", "item");

꽤 기본적인 건데, 뭐가 더 필요하신지 모르겠네요.'/'이(가) 두 배로 증가하는 것이 두렵다면 다음과 같이 간단히 수행할 수 있습니다..Replace("//", "/")ㅠㅠ 만약 이 '에서 것이 에 하나의 을 바꾼 하세요. (는 올바른 읽기 에 '가 있는 모든 만약 당신이 'https://'에서 이중 '//'를 바꾸는 것이 두렵다면, 대신 하나의 조인을 하고, 이중 '/'을 바꾼 다음, 웹사이트 URL에 가입하세요. (그러나 대부분의 브라우저는 앞에 'https:'가 있는 모든 것을 자동으로 변환하여 올바른 형식으로 읽게 될 것입니다.)이는 다음과 같습니다.

string urlToImage = String.Join("/","websiteUrl", String.Join("/", "folder1", "folder2", "folder3", "item").Replace("//","/"));

위의 모든 사항을 처리할 수 있는 답변이 여기에 많이 있지만, 저의 경우 한 위치에서 한 번만 필요하고 크게 의존할 필요가 없습니다.또한, 여기서 무슨 일이 일어나고 있는지 보는 것은 정말 쉽습니다.

참조: https://learn.microsoft.com/en-us/dotnet/api/system.string.join?view=netframework-4.8

Flurl과 같은 종속성을 원하지 않는 경우 소스 코드를 사용할 수 있습니다.

    /// <summary>
    /// Basically a Path.Combine for URLs. Ensures exactly one '/' separates each segment,
    /// and exactly on '&amp;' separates each query parameter.
    /// URL-encodes illegal characters but not reserved characters.
    /// </summary>
    /// <param name="parts">URL parts to combine.</param>
    public static string Combine(params string[] parts) {
        if (parts == null)
            throw new ArgumentNullException(nameof(parts));

        string result = "";
        bool inQuery = false, inFragment = false;

        string CombineEnsureSingleSeparator(string a, string b, char separator) {
            if (string.IsNullOrEmpty(a)) return b;
            if (string.IsNullOrEmpty(b)) return a;
            return a.TrimEnd(separator) + separator + b.TrimStart(separator);
        }

        foreach (var part in parts) {
            if (string.IsNullOrEmpty(part))
                continue;

            if (result.EndsWith("?") || part.StartsWith("?"))
                result = CombineEnsureSingleSeparator(result, part, '?');
            else if (result.EndsWith("#") || part.StartsWith("#"))
                result = CombineEnsureSingleSeparator(result, part, '#');
            else if (inFragment)
                result += part;
            else if (inQuery)
                result = CombineEnsureSingleSeparator(result, part, '&');
            else
                result = CombineEnsureSingleSeparator(result, part, '/');

            if (part.Contains("#")) {
                inQuery = false;
                inFragment = true;
            }
            else if (!inFragment && part.Contains("?")) {
                inQuery = true;
            }
        }
        return EncodeIllegalCharacters(result);
    }

    /// <summary>
    /// URL-encodes characters in a string that are neither reserved nor unreserved. Avoids encoding reserved characters such as '/' and '?'. Avoids encoding '%' if it begins a %-hex-hex sequence (i.e. avoids double-encoding).
    /// </summary>
    /// <param name="s">The string to encode.</param>
    /// <param name="encodeSpaceAsPlus">If true, spaces will be encoded as + signs. Otherwise, they'll be encoded as %20.</param>
    /// <returns>The encoded URL.</returns>
    public static string EncodeIllegalCharacters(string s, bool encodeSpaceAsPlus = false) {
        if (string.IsNullOrEmpty(s))
            return s;

        if (encodeSpaceAsPlus)
            s = s.Replace(" ", "+");

        // Uri.EscapeUriString mostly does what we want - encodes illegal characters only - but it has a quirk
        // in that % isn't illegal if it's the start of a %-encoded sequence https://stackoverflow.com/a/47636037/62600

        // no % characters, so avoid the regex overhead
        if (!s.Contains("%"))
            return Uri.EscapeUriString(s);

        // pick out all %-hex-hex matches and avoid double-encoding 
        return Regex.Replace(s, "(.*?)((%[0-9A-Fa-f]{2})|$)", c => {
            var a = c.Groups[1].Value; // group 1 is a sequence with no %-encoding - encode illegal characters
            var b = c.Groups[2].Value; // group 2 is a valid 3-character %-encoded sequence - leave it alone!
            return Uri.EscapeUriString(a) + b;
        });
    }

다음은 유용하고 다음과 같은 기능이 있습니다.

  • null 또는 공백을 발생시킵니다.
  • 개의 러개사용을 합니다.params Url 세그먼트에 변수 URL 한에 대개 매변수 여트먼
  • null 또는 빈 값을 발생시킵니다.

학급

public static class UrlPath
{
   private static string InternalCombine(string source, string dest)
   {
      if (string.IsNullOrWhiteSpace(source))
         throw new ArgumentException("Cannot be null or white space", nameof(source));

      if (string.IsNullOrWhiteSpace(dest))
         throw new ArgumentException("Cannot be null or white space", nameof(dest));

      return $"{source.TrimEnd('/', '\\')}/{dest.TrimStart('/', '\\')}";
   }

   public static string Combine(string source, params string[] args) 
       => args.Aggregate(source, InternalCombine);
}

테스트

UrlPath.Combine("test1", "test2");
UrlPath.Combine("test1//", "test2");
UrlPath.Combine("test1", "/test2");

// Result = test1/test2

UrlPath.Combine(@"test1\/\/\/", @"\/\/\\\\\//test2", @"\/\/\\\\\//test3\") ;

// Result = test1/test2/test3

UrlPath.Combine("/test1/", "/test2/", null);
UrlPath.Combine("", "/test2/");
UrlPath.Combine("/test1/", null);

// Throws an ArgumentException

그래서 저는 URI Builder를 사용했던 모든 사람들과 비슷한 다른 접근법을 가지고 있습니다.

저는 제 기본Url(경로의 일부를 포함할 수 있음)을 분할하고 싶지 않았습니다(예: javajavajavajavajavajavajavajavajavajavajavajavajavajavajavajavajava가

다음 스니펫은 코드 + 테스트를 보여줍니다.

주의: 이 솔루션은 호스트의 대소문자를 구분하고 포트를 추가합니다.만약 이것이 원하지 않는다면, 예를 들어, 그것을 활용하여 문자열 표현을 쓸 수 있습니다.UriUriBuilder.

  public class Tests
  {
         public static string CombineUrl (string baseUrl, string path)
         {
           var uriBuilder = new UriBuilder (baseUrl);
           uriBuilder.Path = Path.Combine (uriBuilder.Path, path);
           return uriBuilder.ToString();
         }

         [TestCase("http://MyUrl.com/", "/Images/Image.jpg", "http://myurl.com:80/Images/Image.jpg")]
         [TestCase("http://MyUrl.com/basePath", "/Images/Image.jpg", "http://myurl.com:80/Images/Image.jpg")]
         [TestCase("http://MyUrl.com/basePath", "Images/Image.jpg", "http://myurl.com:80/basePath/Images/Image.jpg")]
         [TestCase("http://MyUrl.com/basePath/", "Images/Image.jpg", "http://myurl.com:80/basePath/Images/Image.jpg")]
         public void Test1 (string baseUrl, string path, string expected)
         {
           var result = CombineUrl (baseUrl, path);

           Assert.That (result, Is.EqualTo (expected));
         }
  }

윈도우즈 10에서 .NET Core 2.1로 테스트되었습니다.

왜 이것이 작동합니까?

그럼에도 불구하고.Path.Combine Windows의 ). 는 이 of 백슬의최반다니환합(Windows의 경우)에서합니다. URIBuilder는 다음의 Setter에서 이 사례를 처리합니다.Path.

https://github.com/dotnet/corefx/blob/master/src/System.Private.Uri/src/System/UriBuilder.cs 에서 가져옴 (전화 내용 주의:string.Replace)

[AllowNull]
public string Path
{
      get
      {
          return _path;
      }
      set
      {
          if ((value == null) || (value.Length == 0))
          {
              value = "/";
          }
          _path = Uri.InternalEscapeString(value.Replace('\\', '/'));
          _changed = true;
      }
 }

이게 최선의 방법입니까?

확실히 이 해결책은 (적어도 제 생각에는) 꽤 자기 설명적입니다.하지만 당신은 .NET API의 문서화되지 않은 "기능"에 의존하고 있습니다(최소한 빠른 구글 검색으로 아무것도 찾지 못했습니다).이는 향후 릴리스에 따라 변경될 수 있으므로 테스트를 통해 방법에 대해 설명하십시오.

https://github.com/dotnet/corefx/blob/master/src/System.Private.Uri/tests/FunctionalTests/UriBuilderTests.cs 에 테스트가 있습니다.Path_Get_Set) ) 어떤검사, 에약만.\올바르게 변환되었습니다.

측면 참고:한 명은 또한 함께 일할 수 있습니다.UriBuilder.Uri가 uri에 uri는 직접적으로 uri로 표시됩니다.System.Urictor

일반 솔루션:

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;
}

Microsoft(OfficeDev PnP)의 UrlUtility 메서드입니다.결합:

    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);
    }

출처: 깃허브

위의 모든 샘플을 읽고 결과적으로 제 자신을 만들었습니다.

static string UrlCombine(params string[] items)
{
    if (items?.Any() != true)
    {
        return string.Empty;
    }

    return string.Join("/", items.Where(u => !string.IsNullOrWhiteSpace(u)).Select(u => u.Trim('/', '\\')));
}

용법

UrlCombine("https://microsoft.com","en-us")

할당이 필요 없는 문자열 생성 버전을 사용하여 성공적으로 사용하고 있습니다.

참고:

  1. 번째 첫 번 문 열 의 자 경 : 사 여 기 구 자 릅 니 를 다 호 분 하 다 용 째 음 우 을 ▁the ims ▁using 다 니 : ▁for ▁separator ▁it ▁tr 자 릅 ▁string 첫 ▁the ▁first 기 번TrimEnd(separator)그래서 끈의 끝에서부터만.
  2. 나머지의 경우: 다음을 사용하여 분리기를 자릅니다.Trim(separator) 경로의 과 끝 의▁so끝모두그▁start.
  3. 후행 슬래시/ 구분 기호를 추가하지 않습니다.이 기능을 추가하기 위해 간단한 수정을 수행할 수 있습니다.

이것이 유용하기를 바랍니다!

/// <summary>
/// This implements an allocation-free string creation to construct the path.
/// This uses 3.5x LESS memory and is 2x faster than some alternate methods (StringBuilder, interpolation, string.Concat, etc.).
/// </summary>
/// <param name="str"></param>
/// <param name="paths"></param>
/// <returns></returns>
public static string ConcatPath(this string str, params string[] paths)
{
    const char separator = '/';
    if (str == null) throw new ArgumentNullException(nameof(str));

    var list = new List<ReadOnlyMemory<char>>();
    var first = str.AsMemory().TrimEnd(separator);

    // get length for intial string after it's trimmed
    var length = first.Length;
    list.Add(first);

    foreach (var path in paths)
    {
        var newPath = path.AsMemory().Trim(separator);
        length += newPath.Length + 1;
        list.Add(newPath);
    }

    var newString = string.Create(length, list, (chars, state) =>
    {
        // NOTE: We don't access the 'list' variable in this delegate since 
        // it would cause a closure and allocation. Instead we access the state parameter.

        // track our position within the string data we are populating
        var position = 0;

        // copy the first string data to index 0 of the Span<char>
        state[0].Span.CopyTo(chars);

        // update the position to the new length
        position += state[0].Span.Length;

        // start at index 1 when slicing
        for (var i = 1; i < state.Count; i++)
        {
            // add a separator in the current position and increment position by 1
            chars[position++] = separator;

            // copy each path string to a slice at current position
            state[i].Span.CopyTo(chars.Slice(position));

            // update the position to the new length
            position += state[i].Length;
        }
    });
    return newString;
}

벤치마크 DotNet 출력 사용:

|                Method |     Mean |    Error |   StdDev |   Median | Ratio | RatioSD |  Gen 0 | Allocated |
|---------------------- |---------:|---------:|---------:|---------:|------:|--------:|-------:|----------:|
| ConcatPathWithBuilder | 404.1 ns | 27.35 ns | 78.48 ns | 380.3 ns |  1.00 |    0.00 | 0.3347 |   1,400 B |
|            ConcatPath | 187.2 ns |  5.93 ns | 16.44 ns | 183.2 ns |  0.48 |    0.10 | 0.0956 |     400 B |

간단한 라이너 하나:

public static string Combine(this string uri1, string uri2) => $"{uri1.TrimEnd('/')}/{uri2.TrimStart('/')}";

@Matt Sharpe의 대답에 영감을 받았습니다.

다음은 저의 접근 방식이며 저도 이를 사용할 것입니다.

public static string UrlCombine(string part1, string part2)
{
    string newPart1 = string.Empty;
    string newPart2 = string.Empty;
    string seperator = "/";

    // If either part1 or part 2 is empty,
    // we don't need to combine with seperator
    if (string.IsNullOrEmpty(part1) || string.IsNullOrEmpty(part2))
    {
        seperator = 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, seperator, newPart2);
}

나는 당신의 삶을 더 편하게 해줄 이 기능을 만들었습니다.

    /// <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에도 사용할 수 있습니다.

용도:

    // 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

나는 그것을 발견했습니다.Uri생성자가 '\'을(를) '/'로 플립합니다.은 수할도있다니습을 사용할 .Path.CombineUri시공자

 Uri baseUri = new Uri("http://MyUrl.com");
 string path = Path.Combine("Images", "Image.jpg");
 Uri myUri = new Uri(baseUri, path);

다음을 사용하는 것이 어떻습니까?

System.IO.Path.Combine(rootUrl, subPath).Replace(@"\", "/")

여기 몇 가지 확장 방법이 있습니다.첫 번째는 경로를 결합하고 두 번째는 URL에 매개 변수를 추가합니다.

    public static string CombineUrl(this string root, string path, params string[] paths)
    {
        if (string.IsNullOrWhiteSpace(path))
        {
            return root;
        }

        Uri baseUri = new Uri(root);
        Uri combinedPaths = new Uri(baseUri, path);

        foreach (string extendedPath in paths)
        {
           combinedPaths = new Uri(combinedPaths, extendedPath);
        }

        return combinedPaths.AbsoluteUri;
    }

    public static string AddUrlParams(this string url, Dictionary<string, string> parameters)
    {
        if (parameters == null || !parameters.Keys.Any())
        {
            return url;
        }

        var tempUrl = new StringBuilder($"{url}?");
        int count = 0;

        foreach (KeyValuePair<string, string> parameter in parameters)
        {
            if (count > 0)
            {
                tempUrl.Append("&");
            }

            tempUrl.Append($"{WebUtility.UrlEncode(parameter.Key)}={WebUtility.UrlEncode(parameter.Value)}");
            count++;
        }

        return tempUrl.ToString();
    }

언급URL : https://stackoverflow.com/questions/372865/path-combine-for-urls

반응형