Хитрость заключается в том, чтобы «пометить» читателя. Если ваш читатель не поддерживает маркировку, вы можете обернуть его в BufferedReader, который делает:
ВАРИАНТ № 1 - Проверить спецификацию и удалить ее
Я считаю, что мой исходный код неправильно писал спецификацию. Исходный код ниже имеет больше смысла:
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 - Найти '<' и продвинуть читателя до этой точки </strong>
Читайте до тех пор, пока не достигнете отметки «<» / сброса: </p>
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);
}
}
}