java - 输入流根据内容由不同的对象处理

标签 java content-type inputstream

我正在编写一个爬虫/解析器,它应该能够处理不同类型的内容,包括 RSS、Atom 和纯 html 文件。为了确定正确的解析器,我编写了一个名为 ParseFactory 的类,它接受一个 URL,尝试检测内容类型,并返回正确的解析器。

不幸的是,使用 URLConnection 中提供的方法检查内容类型并不总是有效。例如,

String contentType = url.openConnection().getContentType();

并不总是提供正确的内容类型(例如,“text/html”应该是 RSS),或者不允许区分 RSS 和 Atom(例如,“application/xml”既可以是 Atom,也可以是 RSS feed)。为了解决这个问题,我开始在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) 方法,但这太频繁地返回 null。

旁注 2:XML 解析器(Atom 和 Rss)基于 SAXParser,即 Jsoup 上的 Html 解析器。

最佳答案

你可以只调用markreset吗?

inputStream = new BufferedInputStream(this.url.openStream());
inputStream.mark(2048); // Or some other sensible number

contentTypeParser.parse(inputStream);
contentType = contentTypeParser.getContentType();
contentEncoding = contentTypeParser.getContentEncoding();

inputstream.reset(); // Let the parser have a crack at it now

关于java - 输入流根据内容由不同的对象处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6774701/

相关文章:

java - 如何解码java中的Unicode编码?

java - 如何更改 getWritableDatabase() 指向路径?

spring - Spring Boot中按内容类型缓存静态文件

java - 内容类型突然丢失

php - Drupal 7 drupal_mail 剥离 HTML?

android - 通过网络/本地主机发送大文件

java - Spring MVC - 页面提交后无法从 bean 列表中检索值

java - 将字符数组与字符串匹配的函数

scala - 如何关闭由 Source.fromFile ("/tmp/foo").getLines() 返回的迭代器关联的流

java - 使用 RestTemplate 获取 InputStream