之前写过一篇java利用JAXB实现对象和xml互转
最近发现如果xml格式为utf-8-bom格式 而不是utf-8格式的时候,jaxb处理会报错。
UTF-8 BOM又叫UTF-8 签名,UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。当文本程序读取到以 EF BB BF开头的字节流时,就知道这是UTF-8编码了。Windows就是使用BOM来标记文本文件的编码方式的。
所以可以了解到Bom是微软的习惯,java是没有直接兼容这种标准,这种标准和普通的utf-8的xml的区别只是在文件开头多了三个字节:EFBBBF
所以我们的处理思路是拿到xml文件之后,读取前三个字节是否是EFBBBF就可以判断是不是utf-8-bom这种格式,移除掉这三个字节就能转换成标准的utf-8,这样jaxb就可以处理了。
新建UTF8BomUtil:
package com.ly.mp.project.utils;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.apache.commons.codec.binary.Hex;
public class UTF8BomUtil {
public static boolean isContainBOM(String filePath) throws IOException {
Path path = Paths.get(filePath);
if (Files.notExists(path)) {
throw new IllegalArgumentException("Path: " + path + " does not exists!");
}
boolean result = false;
byte[] bom = new byte[3];
try (InputStream is = new FileInputStream(path.toFile())) {
// read first 3 bytes of a file.
is.read(bom);
// BOM encoded as ef bb bf
String content = new String(Hex.encodeHex(bom));
if ("efbbbf".equalsIgnoreCase(content)) {
result = true;
}
}
return result;
}
public static void main(String[] args) throws IOException {
String utf8BomPath = "D://tmp/utf8bomTest/Application_and_calibration.odx-f";
boolean flag = UTF8BomUtil.isContainBOM(utf8BomPath);
System.out.println(flag);
}
}
上面这个方法可以识别utf-8-bom文件,接下来去掉开头这三个字节即可,可以用
org.apache.commons.io.FileUtils;
public static void removeByte(String filePath, int byteSize) throws IOException {
File file = new File(filePath);
byte[] bytes = FileUtils.readFileToByteArray(file);
byte[] bytesNew = new byte[bytes.length - byteSize];
for(long i = 0; i < bytes.length; i++) {
if(i >= byteSize) {
bytesNew[(int) (i-byteSize)] = bytes[(int) i];
}
}
FileUtils.writeByteArrayToFile(file, bytesNew);
}
网友评论