[问题]
由于开发需要,编写了一个简单的单元测试框架,在基类中从类路径加载资源,并执行初始化动作(类似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"为空格,来解决临时这个问题,这样很不好吧,有中文怎么办?
分享到:
相关推荐
NULL 博文链接:https://liuu.iteye.com/blog/316558
经络学说中存在的瑕疵与疑惑,王维兵,王玉玲,目的:分析经络学说中存在的瑕疵与疑惑,为修正经络学说奠定基础。方法:以《内经》、《难经》、高校教材《经络学》等为依据,与
“脾裹血”功能与实质的现代释义,刘雅峰,王佳,经考证历史文献,结合临床实践认为,《难经》中提出的
第五次作业函数第一题--
本项目旨在利用深度学习方法实现作物病害的自动诊断。作物病害是农业生产中的重要问题,及时诊断和处理对于减少产量损失至关重要。 我们采用深度学习算法,通过分析作物的图像,实现对病害的自动识别和分类。项目使用的数据集包括公开的作物病害图像数据集,如ISIC等,并进行了预处理,包括图像增强、分割和特征提取等。 在运行环境方面,我们使用Python编程语言,基于TensorFlow、PyTorch等深度学习框架进行开发。为了提高计算效率,我们还使用了GPU加速计算。此外,我们还采用了Docker容器技术,确保实验结果的可重复性。 项目完成后,将实现对作物病害的快速、准确诊断,为农业生产提供有力支持,有助于减少产量损失。同时,项目成果也可应用于其他图像识别和分类任务。
机械设计CD驱动印刷设备step非常好的设计图纸100%好用.zip
python烟花代码
附件中是一个简单的烟花效果的代码示例: 在Python中,可以使用多种方式来模拟烟花效果,其中一种常用的方法是使用turtle模块,它提供了一个画布和一个小海龟,可以用来绘制各种图形。 这段代码首先导入了turtle模块和random模块,然后在屏幕上绘制了10次烟花爆炸的效果。每次爆炸都是由5个小圆组成,颜色随机选择,圆的大小也是随机的。 请注意,这段代码需要在支持turtle模块的Python环境中运行,并且需要有图形界面的支持。如果你在没有图形界面的环境中(比如某些服务器或者命令行界面),这段代码可能无法正常运行。
商业化产品经理,到底如何实现产品商业化?.docx
Panduit 工业以太网部件内部销售指南
在Java中,实现一个三维装箱(也称为三维背包问题)的算法通常涉及到组合优化和动态规划。这个问题是一个典型的优化问题,其中目标是在三个维度的限制下最大化价值的总和。下面是一个简单的Java代码示例,它使用动态规划来解决三维装箱问题。 请注意,这个代码只是一个简单的示例,它假设所有物品的第三个维度的大小都是1,并且没有给出如何回溯选择物品的完整逻辑。在实际应用中,三维装箱问题可能更加复杂,需要考虑所有三个维度的限制,并且可能需要更复杂的算法来解决。 此外,这个问题的解决方案可能需要根据具体问题的要求进行调整,例如物品是否可以分割、是否允许超过一个的物品等。如果你有特定的问题描述或者需要进一步的帮助,请提供更多的细节。
常用品牌EPLAN部件库
单片机开发的教程可以分为以下几个步骤: 1. 了解单片机基础知识:在学习单片机开发之前,需要了解单片机的相关知识,包括单片机的基本结构、指令系统、编程语言等。 2. 选择开发板:选择一款适合自己学习开发板的型号和厂商,通常需要关注开发板的性价比、开发环境是否友好等因素。 3. 学习开发环境:根据所选的开发板,学习相关的开发环境和使用方法,例如Keil、IAR等集成开发环境。 4. 掌握编程语言:单片机常用的编程语言包括C语言和汇编语言,根据实际情况选择其中一种进行学习。 5. 基础操作:熟悉单片机的引脚定义和IO口配置,了解单片机的启动代码,可以通过修改启动代码进行基本功能调试。 6. 综合实践:根据具体项目需求,进行单片机开发的综合实践。在实践中需要掌握如何编写程序、如何进行硬件调试、如何使用相关工具软件等技能。 下面是一个单片机开发的简单教程介绍: 首先,确定所使用的单片机型号和开发板类型。在这个阶段,需要查阅相关资料,了解开发板的规格书、芯片规格等基本资料。 其次,安装并配置开发环境。根据所选的开发板,安装相应的集成开发环境(IDE),并配置好开发环境。 接着,学习并掌
Q1.ipynb
(自适应手机端)IT网络建站公司pbootcms模板 互联网营销企业网站源码下载.zip
Bematech 激光扫描器用户手册
激励视频接入文档.pdf
java jdk1.8 202版本下载window linux打包
Lite Beam M5快速指南
互联网金融导论.docx