URL.getFile()

来源:互联网 发布:c语言playsound函数 编辑:程序博客网 时间:2024/05/29 07:58

为了确认问题,我单独建了一个测试项目,写了一个测试类,分别在Java1.4.2、Java5、Java6下运行, 结果确实让我惊讶:

Java代码  收藏代码
  1. public class URLTest {  
  2.     public static void main(String[] args) {  
  3.           
  4.         URL url1 = URLTest.class.getResource("te st.txt");  
  5.         URL url2 = URLTest.class.getResource("中文.txt");  
  6.           
  7.         System.out.println("te st.txt => " + url1.getFile() + ", exist => " + new File(url1.getFile()).exists());  
  8.         System.out.println("中文.txt => " + url2.getFile() + ", exist => " + new File(url2.getFile()).exists());  
  9.     }   
  10. }  

其中“te st.txt”和"中文.txt"是和测试类放在一起的测试文件。

 

 Java1.4.2下输出:

Console代码  收藏代码
  1. te st.txt => /E:/CODE/Test/bin/url/te st.txt, exist => true  
  2. 中文.txt => /E:/CODE/Test/bin/url/中文.txt, exist => true  

 

Java5和Java6均输出:

Console代码  收藏代码
  1. te st.txt => /E:/CODE/Test/bin/url/te%20st.txt, exist => false  
  2. 中文.txt => /E:/CODE/Test/bin/url/%e4%b8%ad%e6%96%87.txt, exist => false  

 

 

看来,原来URL.getFile()是在1.4.2下能自动解码的,到了老虎和野马那里却不灵了,从而导致找不到资源文件。找到了问题,我长舒了一口气。

 

既然问题已经找到,答案呼之欲出,不过,为什么Java5以后要修改URL的行为,不再自动解码呢?我还是有些疑惑。

 

接下来,我一不做二不休,不就是类路径么,我再改,把编译路径从“bin”改成“bin all”,中间加空格,再次运行。。。。。。

 

Java1.4.2下输出:

Console代码  收藏代码
  1. te st.txt => /E:/CODE/Test/bin%20all/url/te st.txt, exist => false  
  2. 中文.txt => /E:/CODE/Test/bin%20all/url/中文.txt, exist => false  

Java5和Java6均输出:

Console代码  收藏代码
  1. te st.txt => /E:/CODE/Test/bin%20all/url/te%20st.txt, exist => false  
  2. 中文.txt => /E:/CODE/Test/bin%20all/url/%e4%b8%ad%e6%96%87.txt, exist => false  

 

哈哈,Java1.4.2的URL终于露馅了,原来它的解码是不完全的!原来URL.getFile()本身就是陷阱啊!即使是在1.4.2下,它也只是给我们一个迷惑的假相。

 

回头想想,为什么Sun要冒着版本不兼容的危险,也要修改URL的行为呢?这或许就是其深层次的原因。

 

[解难]

搞清楚了问题的症结,按方抓药即可。URLDecoder正是用来干这个活的,同时祭出Google,看看同志们是不是早就搞定这个问题了,放眼望去,URL.getFile()搜出来的结果还真不少啊,连带上URL.getPath()也受到牵连,而且URL.getFile()和URL.getPath()得到的路径还可能不一致!又是一个陷阱啊。

 

终解,用URLDecoder:

Java代码  收藏代码
  1. System.out.println("te st.txt =decode=> " + URLDecoder.decode(url1.getFile(), "UTF-8"));  
  2. System.out.println("中文.txt =decode=> " + URLDecoder.decode(url2.getFile(), "UTF-8"));  

 

另外,URI也是可以自动解码的:

Java代码  收藏代码
  1. System.out.println("te st.txt =uri=> " + new URI(url1.getFile()).getPath());  
  2. System.out.println("te st.txt =uri=> " + new URI(url2.getFile()).getPath());  

 

在Java5和Java6下运行,二者皆输出正常:

Console代码  收藏代码
  1. te st.txt => /E:/CODE/Test/bin%20all/url/te%20st.txt, exist => false  
  2. 中文.txt => /E:/CODE/Test/bin%20all/url/%e4%b8%ad%e6%96%87.txt, exist => false  
  3. te st.txt =decode=> /E:/CODE/Test/bin all/url/te st.txt  
  4. 中文.txt =decode=> /E:/CODE/Test/bin all/url/中文.txt  
  5. te st.txt =uri=> /E:/CODE/Test/bin all/url/te st.txt  
  6. te st.txt =uri=> /E:/CODE/Test/bin all/url/中文.txt  

 

不过,1.4.2下,URI又可能是一个陷阱:

Console代码  收藏代码
  1. te st.txt => /E:/CODE/Test/bin/url/te st.txt, exist => true  
  2. 中文.txt => /E:/CODE/Test/bin/url/中文.txt, exist => true  
  3. te st.txt =decode=> /E:/CODE/Test/bin/url/te st.txt  
  4. 中文.txt =decode=> /E:/CODE/Test/bin/url/中文.txt  
  5. java.net.URISyntaxException: Illegal character in path at index 24: /E:/CODE/Test/bin/url/te st.txt  
  6.     at java.net.URI$Parser.fail(URI.java:2752)  
  7.     at java.net.URI$Parser.checkChars(URI.java:2925)  
  8.     at java.net.URI$Parser.parseHierarchical(URI.java:3009)  
  9.     at java.net.URI$Parser.parse(URI.java:2967)  
  10.     at java.net.URI.<init>(URI.java:574)  
  11.     at url.URLTest.main(URLTest.java:24)  
  12. Exception in thread "main"   

URI对于不完整解码的路径,会抛语法异常。