У меня следующая проблема: моей программе передан InputStream, содержимое которого я не могу контролировать. Я отменяю поток ввода, используя библиотеку javax, которая по праву выдает исключения, если InputStream включает символ &, за которым не следует «amp;»
Обходной путь, который я нашел, заключался в создании следующего класса:
import java.io.ByteArrayInputStream;
import java.io.FilterInputStream;
import java.io.InputStream;
/**
* Provide an input stream where all & characters are properly encoded as &
*/
public class FormattedStream extends FilterInputStream {
public FormattedStream(InputStream src) {
super(new ByteArrayInputStream(StringUtil.toString(src)
.replace("&", "&").replace("amp;amp;", "amp;").getBytes()));
}
}
Примечание: StringUtil - это простая утилита, мне нужно превратить входной поток в строку.
С этим классом я теперь вызываю демаршаллер JAXB с:
unmarshal(new FormattedStream(inputStream));
вместо
unmarshal(inputStream);
Этот подход работает, но кажется странным по нескольким причинам:
1 - Из-за ограничения, что super должен быть первым элементом в конструкторе (ограничение, которое я не могу понять, несмотря на то, что я о нем читал), я вынужден выполнять всю свою обработку в одной строке, делая код далеко из читабельного.
2 - Преобразование всего потока в строку и обратно в поток кажется излишним
3 - приведенный выше код немного некорректен в том, что поток содержит amp; amp; будет изменен на содержащий ампер
Я мог бы обратиться к 1, предоставив класс FormatInputStream одним методом:
InputStream preProcess(InputStream inputStream)
, где я выполнял бы те же операции, которые я сейчас выполняю в конструкторе моего класса FormattedStream, но кажется странным, что приходится выбирать другой интерфейс из-за ограничения кодирования.
Я мог бы обратиться к 2, сохранив простой конструктор FormattedStream:
super(src)
и переопределение трех методов чтения, но это потребовало бы гораздо больше кодирования: переопределение трех методов чтения путем замены & на лету не тривиально по сравнению с одной строкой кода, который у меня есть на данный момент, где я могу использовать replaceAll String способ.
Что касается 3, то, похоже, достаточно углового футляра, чтобы я не волновался об этом, но, возможно, мне следует ...
Любые предложения о том, как решить мою проблему более элегантным способом?