【问题标题】:Android: how to parse URL String with spaces to URI object?Android:如何将带有空格的 URL 字符串解析为 URI 对象?
【发布时间】:2010-04-07 14:21:28
【问题描述】:

我有一个表示包含空格的 URL 的字符串,并希望将其转换为 URI 对象。如果我只是尝试通过

创建它
String myString = "http://myhost.com/media/File Name that has spaces inside.mp3";
URI myUri = new URI(myString);

它给了我

java.net.URISyntaxException: Illegal character in path at index X

其中 index X 是 URL 字符串中第一个空格的位置。

如何将myString 解析为URI 对象?

【问题讨论】:

    标签: java android url uri httprequest


    【解决方案1】:

    您实际上应该URI-encode“无效”字符。由于字符串实际上包含完整的 URL,因此很难对其进行正确的 URI 编码。您不知道应该考虑哪些斜杠/,哪些不应该考虑。您无法事先在原始String 上预测这一点。这个问题确实需要在更高的层次上解决。 String 来自哪里?它是硬编码的吗?然后自己相应地更改它。它是否作为用户输入出现?验证并显示错误,让用户自己解决。

    无论如何,如果你能确保它是 only URL 中的空格使其无效,那么你也可以用%20 进行逐个字符串替换:

    URI uri = new URI(string.replace(" ", "%20"));
    

    或者,如果您可以确保它是最后一个斜杠之后需要进行 URI 编码的部分,那么您也可以在 android.net.Uri 实用程序类的帮助下这样做:

    int pos = string.lastIndexOf('/') + 1;
    URI uri = new URI(string.substring(0, pos) + Uri.encode(string.substring(pos)));
    

    请注意,URLEncoder 不适合该任务,因为它旨在按照 application/x-www-form-urlencoded 规则(用于 HTML 表单)对查询字符串参数名称/值进行编码。另见Java URL encoding of query string parameters

    【讨论】:

    • @Mannaz - 当歌曲名称中出现另一个“无效”符号时要小心。
    • @BalusC 我试过 URLEncoder.encode("query string","UTF-8");它以 + 符号返回,例如“query+string”,我期待“%20”。所以我使用 string.replace 硬编码的值。解决了这个问题。谢谢(你的)信息。有没有其他方法可以编码而不是手动替换..?
    【解决方案2】:
    java.net.URLEncoder.encode(finalPartOfString, "utf-8");
    

    这将URL-encode 字符串。

    finalPartOfString 是最后一个斜线之后的部分 - 在您的情况下,它是歌曲的名称。

    【讨论】:

    • 它还会对冒号和斜杠进行urlencode,这会使url仍然无效。他基本上只需要对空格进行urlencode即可使其有效。
    • 好的,这让我得到了URISyntaxException,但现在我从服务器得到了 404。我得到的网址是http://myhost.com/media/mp3s/9/Agenda+of+swine+-+13.+Persecution+Ascension_+leave+nothing+standing.mp3。我在 org.apache.http.client.methods.HttpGet.HttpGet 请求中使用 URI。有什么想法吗?
    • @Mannaz 现在这是另一回事 - 您必须显示 servlet 代码 - 或者更好的是,问另一个问题。问题不再出在客户端上。
    • @Bozho shure 这是客户端/编码问题,因为在普通浏览器中请求原始 URL (myString) 不会导致 404 错误。
    • 我正在使用 java.net.URLEncoder.encode("aa bb cc", "utf-8");但不是添加 %20 而不是空格,而是替换 +。 “aa+bb+cc”。为什么会这样。
    【解决方案3】:

    要处理 url 路径中任意位置的空格、@ 和其他不安全字符,请结合使用 Uri.Builder 与本地 URL 实例,正如我在 here 中描述的那样:

    private Uri.Builder builder;
    public Uri getUriFromUrl(String thisUrl) {
        URL url = new URL(thisUrl);
        builder =  new Uri.Builder()
                                .scheme(url.getProtocol())
                                .authority(url.getAuthority())
                                .appendPath(url.getPath());
        return builder.build();
    }
    

    【讨论】:

      【解决方案4】:
      URL url = Test.class.getResource(args[0]);  // reading demo file path from                                                   
                                                  // same location where class                                    
      File input=null;
      try {
          input = new File(url.toURI());
      } catch (URISyntaxException e1) {
          // TODO Auto-generated catch block
          e1.printStackTrace();
      }
      

      【讨论】:

      • 因为这没有回答问题。
      • 我已经给出了这个用于从 URL 中删除空间的方法,因此它解决了我的问题,因为在读取文件位置 FileInputStream 指向 null 并且使用 null 读取时,它会使用我没有得到的 URI 抛出异常 bu问题。
      【解决方案5】:

      我写了这个函数:

      public static String encode(@NonNull String uriString) {
          if (TextUtils.isEmpty(uriString)) {
              Assert.fail("Uri string cannot be empty!");
              return uriString;
          }
          // getQueryParameterNames is not exist then cannot iterate on queries
          if (Build.VERSION.SDK_INT < 11) {
              return uriString;
          }
      
          // Check if uri has valid characters
          // See https://tools.ietf.org/html/rfc3986
          Pattern allowedUrlCharacters = Pattern.compile("([A-Za-z0-9_.~:/?\\#\\[\\]@!$&'()*+,;" +
                  "=-]|%[0-9a-fA-F]{2})+");
          Matcher matcher = allowedUrlCharacters.matcher(uriString);
          String validUri = null;
          if (matcher.find()) {
              validUri = matcher.group();
          }
          if (TextUtils.isEmpty(validUri) || uriString.length() == validUri.length()) {
              return uriString;
          }
      
          // The uriString is not encoded. Then recreate the uri and encode it this time
          Uri uri = Uri.parse(uriString);
          Uri.Builder uriBuilder = new Uri.Builder()
                  .scheme(uri.getScheme())
                  .authority(uri.getAuthority());
          for (String path : uri.getPathSegments()) {
              uriBuilder.appendPath(path);
          }
          for (String key : uri.getQueryParameterNames()) {
              uriBuilder.appendQueryParameter(key, uri.getQueryParameter(key));
          }
          String correctUrl = uriBuilder.build().toString();
          return correctUrl;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-05-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-18
        • 1970-01-01
        相关资源
        最近更新 更多