Java中将SAP返回的十六进制串转字节解决Apache POI OOXML报错问题
问题原因
- 你当前的错误核心是直接对十六进制字符串调用
getBytes()方法做转换:该方法是将字符串的每个字符单独编码为字节,比如十六进制中的50会被转为代表字符5的0x35、代表字符0的0x30两个字节,而非你需要的十六进制对应二进制值0x50,最终得到的字节数组完全不是合法的DOCX(ZIP格式)二进制流,因此Apache POI会抛出格式错误。
解决方案
方案1:JDK 17+ 原生实现(无第三方依赖)
JDK 17开始提供了内置的HexFormat工具类,可直接完成十六进制串到字节数组的转换:
// 你的十六进制字符串 String hexStr = "504B030414000600080000002100DFA4D26C5A01000020050000130008025B436F6E74656E745F54797065735D2E786D6C20A2040228A0000200000000000000"; // 十六进制转字节数组 byte[] byteArr = HexFormat.of().parseHex(hexStr); InputStream fis = new ByteArrayInputStream(byteArr); return new XWPFDocument(OPCPackage.open(fis));
方案2:低版本JDK 自定义实现(无第三方依赖)
如果你的项目JDK版本低于17,可以自己实现十六进制转字节数组的逻辑:
public static byte[] hexToBytes(String hexStr) { int len = hexStr.length(); byte[] bytes = new byte[len / 2]; for (int i = 0; i < len; i += 2) { bytes[i / 2] = (byte) ((Character.digit(hexStr.charAt(i), 16) << 4) + Character.digit(hexStr.charAt(i+1), 16)); } return bytes; } // 调用示例 byte[] byteArr = hexToBytes(你的十六进制字符串); InputStream fis = new ByteArrayInputStream(byteArr); return new XWPFDocument(OPCPackage.open(fis));
方案3:基于Apache Commons Codec实现
如果项目已经引入Apache Commons Codec依赖,可以直接用Hex工具类:
byte[] byteArr = Hex.decodeHex(你的十六进制字符串.toCharArray()); InputStream fis = new ByteArrayInputStream(byteArr); return new XWPFDocument(OPCPackage.open(fis));
校验小技巧
转换完成后可以先校验字节数组前4个字节,合法的DOCX(ZIP格式)文件头固定为0x50 0x4B 0x03 0x04,和你拿到的十六进制串开头的504B0304对应,只要头匹配就说明转换逻辑正确。
内容的提问来源于stack exchange,提问作者Sherif El Nayad
相关产品推荐
相关产品推荐

