使用JAXB解析UTF-16编码XML遇“序言不允许内容”异常求助
问题分析与解决方案
出现"Content is not allowed in prolog."异常的核心原因是编码不匹配,具体来说是你指定的UTF-16编码和文件实际的UTF-16编码格式(带BOM的小端/大端)不兼容,导致JAXB解析时把文件开头的字节(比如BOM)当成了XML声明前的非法内容。
原因拆解
UTF-16分为两种字节序:UTF-16LE(小端)和UTF-16BE(大端),通常Windows生成的UTF-16文件会带**BOM(字节顺序标记)**来标识字节序。你代码里直接用StandardCharsets.UTF_16,它对应的是不带BOM的默认字节序(取决于系统),如果文件实际是带BOM的UTF-16LE,用这个编码读取会把BOM解析成乱码字符,出现在XML声明<?xml...?>之前,触发异常。
另外,当你用Reader传入JAXB时,JAXB会完全依赖你指定的编码,忽略XML声明里的编码配置,这也放大了编码不匹配的问题。
解决方案
1. 直接使用InputStream让JAXB自动处理编码
这是最稳妥的方式,JAXB会自动读取XML声明里的编码,同时处理BOM:
JAXBContext jaxbContext = JAXBContext.newInstance(MarkerDto.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); InputStream inputStream = new FileInputStream("D:/marker.xml"); // 直接传入InputStream,JAXB会自动检测编码和BOM MarkerDto markerDto = (MarkerDto) jaxbUnmarshaller.unmarshal(inputStream); inputStream.close();
2. 匹配文件实际的UTF-16编码类型
如果你坚持用Reader,需要确认文件的实际编码:
- 如果是带BOM的UTF-16LE(Windows常见),用
StandardCharsets.UTF_16LE:
Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_16LE);
- 如果是UTF-16BE,用
StandardCharsets.UTF_16BE。
3. 检查文件开头是否有非法字符
用文本编辑器(比如Notepad++)打开文件,查看XML声明前是否有空格、换行或其他不可见字符,有的话直接删除即可。
内容的提问来源于stack exchange,提问作者ca2so
相关产品推荐
相关产品推荐

