诀窍是“标记”阅读器。如果您的阅读器不支持标记,您可以将其包装在 BufferedReader 中:
选项 #1 - 检查 BOM 并将其删除
我相信我的原始代码错误地编写了 BOM。下面的源代码更有意义:
import java.io.*;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
public class Demo {
private static char[] UTF32BE = {0x00, 0x00, 0xFE, 0xFF};
private static char[] UTF32LE = {0xFF, 0xFE, 0x00, 0x00};
private static char[] UTF16BE = {0xFE, 0xFF};
private static char[] UTF16LE = {0xFF, 0xFE};
private static char[] UTF8 = {0xEF, 0xBB, 0xBF};
public static void main(String[] args) throws Exception {
// Create an XML document with a BOM
FileOutputStream fos = new FileOutputStream("bom.xml");
writeBOM(fos, UTF16LE);
OutputStreamWriter oswUTF8 = new OutputStreamWriter(fos, "UTF-8");
oswUTF8.write("<root/>");
oswUTF8.close();
// Create a Source based on a Reader to simulate source.getRequest()
StreamSource attachment = new StreamSource(new FileReader(new File("bom.xml")));
// Wrap reader in BufferedReader so it will support marking
Reader reader = new BufferedReader(attachment.getReader());
// Remove the BOM
removeBOM(reader);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
t.transform(new StreamSource(reader), new StreamResult(System.out));
}
private static void writeBOM(OutputStream os, char[] bom) throws Exception {
for(int x=0; x<bom.length; x++) {
os.write((byte) bom[x]);
}
}
private static void removeBOM(Reader reader) throws Exception {
if(removeBOM(reader, UTF32BE)) {
return;
}
if(removeBOM(reader, UTF32LE)) {
return;
}
if(removeBOM(reader, UTF16BE)) {
return;
}
if(removeBOM(reader, UTF16LE)) {
return;
}
if(removeBOM(reader, UTF8)) {
return;
}
}
private static boolean removeBOM(Reader reader, char[] bom) throws Exception {
int bomLength = bom.length;
reader.mark(bomLength);
char[] possibleBOM = new char[bomLength];
reader.read(possibleBOM);
for(int x=0; x<bomLength; x++) {
if(bom[x] != possibleBOM[x]) {
reader.reset();
return false;
}
}
return true;
}
}
选项 #2 - 找到“<”并将阅读器提前到该点
阅读直到你点击'<'利用标记/重置:
import java.io.*;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
public class Demo2 {
private static char[] UTF32BE = {0x00, 0x00, 0xFE, 0xFF};
private static char[] UTF32LE = {0xFF, 0xFE, 0x00, 0x00};
private static char[] UTF16BE = {0xFE, 0xFF};
private static char[] UTF16LE = {0xFF, 0xFE};
private static char[] UTF8 = {0xEF, 0xBB, 0xBF};
public static void main(String[] args) throws Exception {
// Create an XML document with a BOM
FileOutputStream fos = new FileOutputStream("bom.xml");
writeBOM(fos, UTF16BE);
OutputStreamWriter oswUTF8 = new OutputStreamWriter(fos, "UTF-8");
oswUTF8.write("<root/>");
oswUTF8.close();
// Create a Source based on a Reader to simulate source.getRequest()
StreamSource attachment = new StreamSource(new FileReader(new File("bom.xml")));
// Wrap reader in BufferedReader so it will support marking
Reader reader = new BufferedReader(attachment.getReader());
// Remove the BOM
removeBOM(reader);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
t.transform(new StreamSource(reader), new StreamResult(System.out));
}
private static void writeBOM(OutputStream os, char[] bom) throws Exception {
for(int x=0; x<bom.length; x++) {
os.write((byte) bom[x]);
}
}
private static Reader removeBOM(Reader reader) throws Exception {
reader.mark(1);
char[] potentialStart = new char[1];
reader.read(potentialStart);
if('<' == potentialStart[0]) {
reader.reset();
return reader;
} else {
return removeBOM(reader);
}
}
}