导出为.jar文件后XML解析失败,Eclipse运行正常,该排查何处?
从错误栈来看,核心问题是XML解析时的UTF-8编码不匹配——具体是写入XML文件时用了错误的字符编码,导致解析器无法正确识别字节序列。结合你提供的代码片段,我来拆解问题和解决步骤:
为什么Eclipse里正常,导出Jar就报错?
你用了FileWriter来写入XML字符串,但FileWriter会默认使用当前系统的默认字符编码(比如Windows下是GBK,Linux下可能是UTF-8)。在Eclipse中运行时,IDE通常会把项目的默认编码设置为UTF-8,并且运行环境的编码也会继承IDE的设置,所以写入的文件是UTF-8编码,解析器能正常处理。但导出成Jar后,运行环境的系统默认编码可能不是UTF-8,导致写入的XML文件用了非UTF-8编码,解析器以UTF-8读取时就抛出了MalformedByteSequenceException。
排查步骤
确认运行Jar的环境编码:在代码中添加一行输出,查看当前系统的默认文件编码:
System.out.println("当前系统默认编码:" + System.getProperty("file.encoding"));如果输出不是
UTF-8,那就是编码不匹配的直接证据。验证XML字符串本身的正确性:在写入文件前,打印
content的前一段内容,确认没有乱码,同时检查服务器返回的响应头Content-Type是否包含charset=utf-8,确保从服务器获取的字符串本身是正确的UTF-8编码。
修复方案
方案1:显式指定写入文件的UTF-8编码
替换FileWriter为OutputStreamWriter,明确指定UTF-8编码,彻底摆脱系统默认编码的影响:
File srcFile = File.createTempFile("src", ".xml"); // 使用try-with-resources自动关闭流,避免资源泄漏 try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(srcFile), StandardCharsets.UTF_8)) { writer.write(content); } DSSDocument doc = new FileDocument(srcFile); ToBeSigned dataToSign = service.getDataToSign(doc, parameters);
方案2:跳过临时文件,直接使用字符串创建DSSDocument
既然你已经有了XML字符串,完全可以不用写入临时文件,直接用StringDocument来包装,这样彻底避免文件编码问题:
// 直接用字符串和指定编码创建DSSDocument DSSDocument doc = new StringDocument(content, StandardCharsets.UTF_8.name()); ToBeSigned dataToSign = service.getDataToSign(doc, parameters);
这个方案更简洁,也减少了IO操作的开销,是更推荐的做法。
额外提醒
处理XML、JSON这类有明确编码规范的文本时,永远不要依赖系统默认编码,一定要显式指定编码,这样你的程序在不同操作系统、不同运行环境下才能保持一致的行为。
内容的提问来源于stack exchange,提问作者Artur

