Java如何批量将XML文件中的十六进制字符实体转为对应字符
Java实现XML十六进制字符实体转原生字符方案
需求背景
- 待处理大型XML文件中存在大量十六进制格式的XML字符实体,格式为
&#x十六进制码点;,例如§对应原生字符§ - 待处理内容示例:
<md.first.line.cite>UT ST § 10-2-409</md.first.line.cite>
- 要求转换后实体替换为对应原生字符,同时适配大文件场景,避免内存溢出。
方案1:原生JDK流式正则替换(无额外依赖,适合超大文件)
核心逻辑是逐行/逐块读取文件,通过正则匹配实体后解析码点替换为对应字符,全程内存仅占用单块读取的缓冲区大小,不会出现大文件OOM问题。
import java.io.*; import java.nio.charset.StandardCharsets; import java.util.regex.Matcher; import java.util.regex.Pattern; public class HexXmlEntityConverter { // 匹配十六进制XML字符实体,捕获组提取十六进制码点 private static final Pattern HEX_ENTITY_PATTERN = Pattern.compile("&#x([0-9a-fA-F]+);"); public static void convert(String inputPath, String outputPath) throws IOException { // 采用带缓冲区的字符流逐行读写,默认8KB缓冲区,内存占用极低 try (BufferedReader reader = new BufferedReader( new InputStreamReader(new FileInputStream(inputPath), StandardCharsets.UTF_8)); BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(outputPath), StandardCharsets.UTF_8))) { String line; while ((line = reader.readLine()) != null) { writer.write(replaceHexEntity(line)); writer.newLine(); } } } private static String replaceHexEntity(String content) { Matcher matcher = HEX_ENTITY_PATTERN.matcher(content); StringBuilder result = new StringBuilder(); while (matcher.find()) { // 解析十六进制码点 int codePoint = Integer.parseInt(matcher.group(1), 16); // 兼容Unicode增补平面字符(如生僻字、emoji),正确处理代理对 matcher.appendReplacement(result, Matcher.quoteReplacement(new String(Character.toChars(codePoint)))); } matcher.appendTail(result); return result.toString(); } public static void main(String[] args) throws IOException { convert("your_input.xml", "your_output.xml"); } }
注意事项
- 如果XML存在单行内容过大的情况,可以把逐行读取改成固定大小字符块读取,替换逻辑和上述代码一致
- 用
Character.toChars(codePoint)处理码点,能正确识别Unicode增补平面字符,不会出现乱码
方案2:基于Apache Commons Text实现(项目已有依赖可直接用)
如果项目中已经引入Apache Commons Text依赖,可以直接使用内置的XML实体解码工具,不需要自己写正则逻辑,读写逻辑和方案1一致,仅替换实体转换的方法即可:
import org.apache.commons.text.StringEscapeUtils; private static String replaceHexEntity(String content) { // 自动解码所有XML实体,包括十六进制实体、十进制实体、XML内置实体(如&、<等) return StringEscapeUtils.unescapeXml(content); }
注意:不要使用旧版commons-lang包中的
StringEscapeUtils,该版本对Unicode增补平面字符的处理存在bug,会导致乱码,请使用commons-text包下的对应方法。
转换效果验证
示例内容转换后输出为:
<md.first.line.cite>UT ST § 10-2-409</md.first.line.cite>
其中§转换为分节符§, 转换为对应宽度的空格,符合预期。
内容的提问来源于stack exchange,提问作者Suprita S B
相关产品推荐
相关产品推荐

