[问题]
由于开发需要,编写了一个简单的单元测试框架,在基类中从类路径加载资源,并执行初始化动作(类似Spring测试基类),利用ClassLoader,加载资源自是驾轻就熟。我自己通过继承这个测试基类,编写了不少测试类,感觉还算方便,也没有出过什么问题。不过,近日其他同事Z在用这个测试基类时,却经常出现加载不到资源的问题,很奇怪。
[探幽]
既然是加载不到资源,还是第一反应,肯定是资源路径有问题,可是我的环境下并没有报这个错啊,看看Z同事的测试类,要加载的资源文件明明就在那,类路径指定也没有问题啊;扫了一眼,看见资源文件的命名是中文的,不过我并没有在意,因为我用中文测过,没有问题。
不是中文问题,那可能是其他什么原因呢?苦思不得其解,回到自己的机器上,调试了一下程序,本机运行依然没有问题,重新审查加载资源的方法实现,用的ClassLoader定位取得URL,再用URL.getFile()取得实际路径,最后new File()读取文件,没什么问题啊?
要真有问题,难道是URL.getFile()不正确?想到这一点,再想想Z君的开发环境,他是在Java5下开发,而我还是坚守者1.4.2阵地,难道?难道Java5下会有问题?我飞快的抓起鼠标,把编译环境改为Tiger,运行,出错!Java5下确实找不到资源!断点调试发现,在Java5下,URL.getFile()返回的资源位置是未解码的,空格和中文成了URL转码格式。URL.getFile(),真的是你让Tiger老虎落入陷阱么?
为了确认问题,我单独建了一个测试项目,写了一个测试类,分别在Java1.4.2、Java5、Java6下运行, 结果确实让我惊讶:
public class URLTest {
public static void main(String[] args) {
URL url1 = URLTest.class.getResource("te st.txt");
URL url2 = URLTest.class.getResource("中文.txt");
System.out.println("te st.txt => " + url1.getFile() + ", exist => " + new File(url1.getFile()).exists());
System.out.println("中文.txt => " + url2.getFile() + ", exist => " + new File(url2.getFile()).exists());
}
}
其中“te st.txt”和"中文.txt"是和测试类放在一起的测试文件。
Java1.4.2下输出:
te st.txt => /E:/CODE/Test/bin/url/te st.txt, exist => true
中文.txt => /E:/CODE/Test/bin/url/中文.txt, exist => true
Java5和Java6均输出:
te st.txt => /E:/CODE/Test/bin/url/te%20st.txt, exist => false
中文.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下输出:
te st.txt => /E:/CODE/Test/bin%20all/url/te st.txt, exist => false
中文.txt => /E:/CODE/Test/bin%20all/url/中文.txt, exist => false
Java5和Java6均输出:
te st.txt => /E:/CODE/Test/bin%20all/url/te%20st.txt, exist => false
中文.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:
System.out.println("te st.txt =decode=> " + URLDecoder.decode(url1.getFile(), "UTF-8"));
System.out.println("中文.txt =decode=> " + URLDecoder.decode(url2.getFile(), "UTF-8"));
另外,URI也是可以自动解码的:
System.out.println("te st.txt =uri=> " + new URI(url1.getFile()).getPath());
System.out.println("te st.txt =uri=> " + new URI(url2.getFile()).getPath());
在Java5和Java6下运行,二者皆输出正常:
te st.txt => /E:/CODE/Test/bin%20all/url/te%20st.txt, exist => false
中文.txt => /E:/CODE/Test/bin%20all/url/%e4%b8%ad%e6%96%87.txt, exist => false
te st.txt =decode=> /E:/CODE/Test/bin all/url/te st.txt
中文.txt =decode=> /E:/CODE/Test/bin all/url/中文.txt
te st.txt =uri=> /E:/CODE/Test/bin all/url/te st.txt
te st.txt =uri=> /E:/CODE/Test/bin all/url/中文.txt
不过,1.4.2下,URI又可能是一个陷阱:
te st.txt => /E:/CODE/Test/bin/url/te st.txt, exist => true
中文.txt => /E:/CODE/Test/bin/url/中文.txt, exist => true
te st.txt =decode=> /E:/CODE/Test/bin/url/te st.txt
中文.txt =decode=> /E:/CODE/Test/bin/url/中文.txt
java.net.URISyntaxException: Illegal character in path at index 24: /E:/CODE/Test/bin/url/te st.txt
at java.net.URI$Parser.fail(URI.java:2752)
at java.net.URI$Parser.checkChars(URI.java:2925)
at java.net.URI$Parser.parseHierarchical(URI.java:3009)
at java.net.URI$Parser.parse(URI.java:2967)
at java.net.URI.<init>(URI.java:574)
at url.URLTest.main(URLTest.java:24)
Exception in thread "main"
URI对于不完整解码的路径,会抛语法异常。
看来,还是Decoder.decode()是最终正解啊,用URI的同学要小心了,请保证你的应用跑在Java5上。
另,看到JavaEye里有兄弟自己替换"%20"为空格,来解决临时这个问题,这样很不好吧,有中文怎么办?
分享到:
相关推荐
标题中的“难经3:Struts2,拦截器拦不住Result?”揭示了这是一个关于Struts2框架中拦截器(Interceptor)与结果(Result)交互问题的讨论。在Struts2框架中,拦截器是实现业务逻辑和控制逻辑之间解耦的重要机制,而...
### 主治医师 (中医全科学)-肺系病证(A1型题 2) #### 喘证发病机制 - **选项解析**: - A. 心和肺:不符合喘证的主要发病机理。 - B. 肝和脾:与喘证发病关系较小。 - C. 肺和脾:虽涉及肺脏但未涵盖肾脏在喘证...
2. 历代代表性针灸著作包括《黄帝内经》、《难经》、《针灸甲乙经》、《针灸大成》等。 本题集详细介绍了针灸学的基本概念、历史发展、主要著作和理论体系,为学习和理解针灸学提供了丰富的素材。通过对这些知识点...
2. 《内经》:《内经》是中医理论的重要基础,其中多次提到与睡眠相关的疾病,如“不得卧”、“卧担心”、“卧不得安”等。例如,在《素问·热论》中提到,阳明脉受邪会导致头痛、腰背僵硬,且伴有无法入睡的症状。...
1. 中医学理论体系的形成始于古代医学典籍的出现,如《黄帝内经》、《难经》、《神农本草经》和《伤寒杂病论》等,这些著作标志着中医理论体系的初步建立,并在随后的晋唐时期得到进一步发展和完善,如《脉经》、...
2. **中医学的根本特点**:主要体现在整体观念、辨证论治和预防为主等方面,强调人体与自然环境的和谐统一,疾病治疗注重个体差异。 3. **中医学理论体系的形成条件**:古代哲学思想、实践经验、古代科学技术的发展...
- 我国古代医学家张角在墓地观察尸体,其著作为《难经》。 - 东汉医家张仲景创立了辩证施治的医则,其著作是《伤寒杂病论》,后来被整理成《伤寒论》和《金匮要略》两部分。 这些题目涉及了医学的多个重要阶段,从...
《难经》 - E. 《左传》 正确答案为E,《左传》。 ### 二、“四变之动,脉与之上下” **知识点概述:** 《素问·脉要精微论》中的这句话体现了中医理论中人与自然环境相统一的观点。古人认为,人的生理变化与...
1. **脉学**:《难经》是中医脉学的重要典籍,其中详细阐述了脉象的分析和理解,对脉象的辨识有独特的见解。 2. **结石形成原因**:结石的形成多与饮食习惯有关,如偏好油腻食物,可能导致脾胃功能障碍,湿热内生,...
《难经》深化了对经络的理解;C.《针灸甲乙经》是最早的一部针灸专著,具有重要历史地位;D.《针灸大成》和E.《针灸大全》都是后世对针灸经验的总结,但《针灸大成》更具代表性,因为它汇集了众多前人的经验和理论。...
2. **古代四大才女**:蔡文姬、班昭、卓文君、李清照,这四位才女在诗词、音乐、书法等领域有着卓越的成就,对后世产生了深远影响。 3. **江南四大才子**:唐伯虎、文征明、祝枝山、徐祯卿,他们是中国明朝时期的...
2. **中医四大经典**:《内经》、《难经》、《伤寒杂病论》、《神农本草经》是中医基础理论形成的标志,它们对后世中医的发展产生了深远影响。 3. **金元四大家**:这四位医家代表了不同的医学流派,如刘完素的寒凉...
本课内容丰富,涵盖了文字演变、文学艺术、科学技术等多个领域,旨在通过学习让学生深入了解中华文化的历史底蕴和辉煌成就,培养他们对中国传统文化的热爱和尊重。同时,教学设计强调了能力培养和价值观的塑造,以期...
2. 脉学专著:《脉经》是王叔和所著,是中国古代第一部系统论述脉理、脉象的著作。 3. 诊法专著《察病指南》的作者是施发。 4. 曹炳章的舌诊专著是《彩图辨舌指南》。 5. 《诸病源候论》是成书于隋代的我国第一部...
2. **咳嗽**的辨证论治:感冒引起的咳嗽是由于肺气失宣和卫表不和,而咳嗽本身是肺气上逆的结果。咳嗽的辨病历史可追溯到《内经》,“五脏六腑皆令人咳”,表明咳嗽不仅限于肺脏问题。 3. **哮**与**喘**的鉴别:...
2. 咳嗽:咳嗽的中医概念早见于《经》,而《素问·咳论》指出五脏六腑皆可引起咳嗽,不仅限于肺。咳嗽分为外感和内伤,病理因素包括痰和火。它既可以是单一病种,也可能出现在多种西医疾病中。 3. 哮与喘:《医学...
2. 对脉学有较详细论述的是《难经》,它是中医经典之一,对脉象的识别和理解有深入阐述。 3. 制备胶囊时,甘油的作用是保持一定的水分,防止胶囊脆裂,确保药物稳定。 4. 慢性浅表性胃炎的特点是胃黏膜浅层淋巴细胞...
5. 五部与五脏的对应关系在《难经》中有详细阐述,左腮对应肝,鼻对应肺,心尖对应心,唇对应脾,耳垂对应肾,这是中医脏腑理论的一部分。 6. 我国传统上会给新生儿进行祛胎毒,常用的方法有清热解毒的中药汤剂、...
根据《难经》的记载,三焦具有“主持诸气”的功能,即它对全身的气化过程起着关键的调节作用。气化是指气在人体内的转化和推动作用,如精化为气、气化为神等。气有六大功能,包括推动、温煦、濡养、防御、固摄和气化...
- 了解中医诊断学在历史上的发展,包括代表性的医家和他们的著作,如《难经》、《伤寒杂病论》等。 6. **具体内容**: - 问诊:包括问寒热、问汗、问疼痛、问头身胸腹、问耳目、问睡眠、问饮食口味、问二便、问经...