Я пишу сканер / анализатор, который должен иметь возможность обрабатывать различные типы контента, такие как RSS, Atom и просто обычные HTML-файлы. Чтобы определить правильный синтаксический анализатор, я написал класс ParseFactory, который принимает URL-адрес, пытается определить тип содержимого и возвращает правильный синтаксический анализатор.
К сожалению, проверка типа содержимого с использованием предоставленного метода in в URLConnection не всегда работает. Например,
String contentType = url.openConnection().getContentType();
не всегда обеспечивает правильный тип содержимого (например, «text / html», где это должно быть RSS) или не позволяет различать RSS и Atom (например, «application / xml» может быть как Atom, так и RSS-канал). Чтобы решить эту проблему, я начал искать подсказки в InputStream. Проблема в том, что у меня возникают проблемы при создании элегантного дизайна класса, когда мне нужно загрузить InputStream только один раз. В моем текущем проекте я сначала написал отдельный класс, который определяет правильный тип содержимого, затем ParseFactory использует эту информацию для создания экземпляра соответствующего анализатора, который, в свою очередь, когда вызывается метод parse (), загружает весь InputStream во второй раз.
public Parser createParser(){
InputStream inputStream = null;
String contentType = null;
String contentEncoding = null;
ContentTypeParser contentTypeParser = new ContentTypeParser(this.url);
Parser parser = null;
try {
inputStream = new BufferedInputStream(this.url.openStream());
contentTypeParser.parse(inputStream);
contentType = contentTypeParser.getContentType();
contentEncoding = contentTypeParser.getContentEncoding();
assert (contentType != null);
inputStream = new BufferedInputStream(this.url.openStream());
if (contentType.equals(ContentTypes.rss))
{
logger.info("RSS feed detected");
parser = new RssParser(this.url);
parser.parse(inputStream);
}
else if (contentType.equals(ContentTypes.atom))
{
logger.info("Atom feed detected");
parser = new AtomParser(this.url);
}
else if (contentType.equals(ContentTypes.html))
{
logger.info("html detected");
parser = new HtmlParser(this.url);
parser.setContentEncoding(contentEncoding);
}
else if (contentType.equals(ContentTypes.UNKNOWN))
logger.debug("Unable to recognize content type");
if (parser != null)
parser.parse(inputStream);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return parser;
}
По сути, я ищу решение, которое позволило бы мне исключить второй "inputStream = new BufferedInputStream (this.url.openStream ())".
Любая помощь будет принята с благодарностью!
Примечание 1: просто для полноты я также попытался использовать метод URLConnection.guessContentTypeFromStream (inputStream), но он слишком часто возвращает ноль.
Примечание 2: XML-парсеры (Atom и Rss) основаны на SAXParser, Html-парсере в Jsoup.