如何解析URI这样在Java中

问题描述:

我试图解析以下URI:http://translate.google.com/#zh-CN|en|你如何解析URI这样在Java中

,但得到这个错误信息:

java.net.URISyntaxException: Illegal character in fragment at index 34: http://translate.google.com/#zh-CN|en|你 
     at java.net.URI$Parser.fail(URI.java:2809) 
     at java.net.URI$Parser.checkChars(URI.java:2982) 
     at java.net.URI$Parser.parse(URI.java:3028) 

它有问题,用“|”字符,如果我摆脱了“|”,最后一个中文字符不会引起任何问题,那么处理这个问题的正确方法是什么?

我的方法是这样的:

public static void displayFileOrUrlInBrowser(String File_Or_Url) 
    { 
    try { Desktop.getDesktop().browse(new URI(File_Or_Url.replace(" ","%20").replace("^","%5E"))); } 
    catch (Exception e) { e.printStackTrace(); } 
    } 

感谢您的答案,但BalusC的解决方案似乎只对URL的一个实例的工作,我的方法需要与任何URL我传递给它的,如何工作它会知道将URL分割成两部分的起点和只编码第二部分的起点?

管道字符是"considered unsafe"用于URL。您可以通过替换|来修复它与其编码的十六进制等效,这将是“%7C”

但是,替换URL中的单个字符是一个脆弱的解决方案,如果您认为在任何给定的URL中可能会有相当的可能需要替换的许多不同的字符。你已经在替换空格,插入符号和管道......但括号,重音符号和引号怎么办?还是问号和&符号,它们可能是也可能不是URL的有效部分,具体取决于它们的使用方式?

因此,优越的解决方案是使用该语言的工具对网址进行编码,而不是手动完成。在Java的情况下,使用URLEncoder,根据BalusC对此问题的回答中的示例。

+6

参考:'URLEncoder'(尽管名称)不应该用于URL编码。该文档说:_此类包含将字符串转换为application/x-www-form-urlencoded MIME格式的静态方法._这与URIs/URL使用的编码不同。 – McDowell 2009-12-01 21:29:48

+0

BalusC的解决方案似乎适用于该实例的url,但我需要该方法适用于所有传递给它的url,它将如何知道从什么起点解析剩余的url? 这个网址就以下任何一项: www.yahoo.com/abc/xyz http://yahoo.com/abc/123/ yahoo.com/abc/123/... – Frank 2009-12-02 02:56:04

+0

我认为你需要将网址分割成片段......域,路径,查询字符串和片段。该域不应该被编码。路径,你将不得不用斜线分割,并对路径的每一部分进行编码,然后再将它们放在一起。对于查询字符串,您需要对每个参数名称和值进行编码。你也必须编码片段。然后,重新组装URL。 – 2009-12-02 03:25:09

好吧,我发现如何做到这一点,就像这样:

try { Desktop.getDesktop().browse(new URI(File_Or_Url.replace(" ","%20").replace("^","%5E").replace("|","%7C"))); } 
catch (Exception e) { e.printStackTrace(); } 
+1

使用URLEncoder。 – 2009-12-01 22:21:52

你不是最好使用URLEncoder不是选择性的编码的东西?

您应该使用java.net.URLEncoderUTF-8对查询进行网址编码。你不一定需要这样的正则表达式。你不想有一个正则表达式来涵盖所有这些数千个中国字形,你呢? ;)

String query = URLEncoder.encode("zh-CN|en|你", "UTF-8"); 
String url = "http://translate.google.com/#" + query; 
Desktop.getDesktop().browse(new URI(url));  

的URLEncoder的解决方案并没有为我工作,也许是因为它编码只是一切。我正在尝试使用Apache的HttpGet,并且它会像URL那样以字符串的形式抛出错误。

在我的情况下,正确的做法应该是这个奇怪的代码:

URL url = new URL(pageURLAsUnescapedString); 
URI uri = new URI(url.getProtocol(), url.getAuthority(), url.getPath(), url.getQuery(), url.getRef()); 

不知怎的url.toURI不相同的方式工作。 URI构造函数有两种工作方式:如果使用带有单个String参数的构造函数,则构造函数假装提供的uri被正确转义(并因此发生错误,这与HttpGet的String构造函数相同);如果您使用多个Strings URI构造函数,那么该类将非常好地处理一切(并且HttpGet具有另一个接受URI的构造函数)。为什么URL.toURI()不这样做?我不知道...

希望它可以帮助某人,我花了几个小时才弄明白。

+0

这是错误的。如果URL包含一些编码字符,例如空格“%20”,结果会有不需要的“%2520”。看看示例[这里](http://ideone.com/7uVSBj)或[我的问题和答案](http://stackoverflow.com/q/13530019/1387438)。 – 2014-03-08 12:18:20

+1

@MarekR我把你最好的两个答案,并结合他们在http://stackoverflow.com/a/22279061/14731 – Gili 2014-03-09 06:11:37

以最好的Federico's answerMarek's answer,你需要做到以下几点:

URL url = new URL(pageURLAsUnescapedString); 

// URI's constructor expects the path, query string and fragment to be decoded. 
// If we do not decode them, we will end up with double-encoding. 
String path = url.getPath(); 
if (path != null) 
    path = URLDecoder.decode(path, "UTF-8"); 
String query = url.getQuery(); 
if (query != null) 
    query = URLDecoder.decode(query, "UTF-8"); 
String fragment = url.getRef(); 
if (fragment != null) 
    fragment = URLDecoder.decode(fragment, "UTF-8"); 

URI uri = new URI(url.getProtocol(), url.getAuthority(), path, query, fragment); 
+0

'URLDecoder.decode(查询,“UTF-8”)''也将在参数值解码符号早 – giorgiga 2015-02-06 09:34:44

首先编码您的网址,请用下面的例子中,再通过URL进入方法

 JSONObject json = new JSONObject(); 
     json.put("name", "vaquar"); 
     json.put("age", "30"); 
     json.put("address", "asasbsa bajsb "); 


     System.out.println("in sslRestClientGETRankColl"+json.toString()); 

     String createdJson=json.toString(); 

     createdJson= URLEncoder.encode(createdJson, "UTF-8"); 

//现在调用方法 displayFileOrUrlInBrowser(createdJson);

public static void displayFileOrUrlInBrowser(String File_Or_Url) 
    { 
    try { Desktop.getDesktop().browse(File_Or_Url); } 
    catch (Exception e) { e.printStackTrace(); } 
    }