使用PrimeFaces <p:fileUpload>解析UTF-8 XML遇异常求助
问题排查与解决方案
嘿,这个问题我之前也碰到过!你遇到的Start of root element expected异常,核心原因其实是**UTF-8 BOM(字节顺序标记)**在搞鬼。
当你用Windows记事本保存UTF-8格式的文件时,它会自动在文件最开头插入三个字节的BOM(十六进制是EF BB BF)。而Oracle的DOMParser默认不会识别并忽略这个标记,会把它当成XML文档的第一个“字符”,导致解析器以为文档开头根本没有合法的XML根元素,直接抛出异常。而ANSI编码的文件本身没有BOM,所以你的代码能正常跑起来。
下面给你几个可行的解决方案:
方案1:读取文件时主动跳过BOM字节
这是最稳妥的代码层面解决方案,修改你的输入流处理逻辑,检查并跳过UTF-8 BOM:
// 注意:这里要替换成用户上传的文件流,不是本地固定路径! InputStream inputStream = event.getFile().getInputStream(); // 检查并跳过UTF-8 BOM if (inputStream.markSupported()) { inputStream.mark(3); byte[] bomBytes = new byte[3]; int readBytes = inputStream.read(bomBytes); if (!(readBytes == 3 && bomBytes[0] == (byte)0xEF && bomBytes[1] == (byte)0xBB && bomBytes[2] == (byte)0xBF)) { // 没有检测到BOM,重置流到起始位置 inputStream.reset(); } } Reader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); InputSource is = new InputSource(new BufferedReader(inputStreamReader)); DOMParser parser = new DOMParser(); parser.parse(is); Document doc = parser.getDocument();
另外提一句:你原来的代码用了本地固定路径C:\\test\\test_ansi.xml,实际在PrimeFaces的fileUploadListener里,应该从UploadedFile对象(比如event.getFile())获取输入流,不然生产环境根本处理不了用户上传的文件哦。
方案2:配置DOMParser忽略BOM(视版本而定)
部分版本的Oracle XML Parser支持通过属性来忽略BOM,你可以试试添加这段配置:
DOMParser parser = new DOMParser(); // 强制指定编码为UTF-8 parser.setProperty("http://xml.org/sax/properties/encoding", "UTF-8"); // 开启忽略BOM的特性(部分版本支持) parser.setProperty("oracle.xml.parser.v2.nobom", Boolean.TRUE); parser.parse(is);
不过这个属性的兼容性可能不如方案1,建议优先用方案1。
方案3:让用户换编辑器保存文件
可以提醒用户不要用记事本保存UTF-8格式的XML文件,改用Notepad++、VS Code这类编辑器,保存时选择「UTF-8无BOM」格式。这是用户侧的操作,只能作为辅助建议,不能替代代码层面的处理。
内容的提问来源于stack exchange,提问作者Tatha
相关产品推荐
相关产品推荐

