URLConnection中的getContent与getInputStream

    最近一直在做数据抓取的工作,以前接触的比较少,偶尔尝试过,但那会儿不太熟。后来看到大学都使用HttpClient来做,我就去下载了然后做了个测试,发现确实很简单,好用。于是我就一直用它来做数据抓取和文件下载的工作,这样用了一段时间,可是在用的过程中经常出现一些莫名奇怪的错误,我想应该是我对它的一些设置或者用法不对。但蛋疼的是它报的错误都是基本的IO错误,根据就不知道为什么。这样继续了快一个月,抓取断断续续的,我实在受不了,就果断换成了JDK自带的HttpURLConnection,这样就再也没出现那样的错误,最多是ReadTimeout,这样我就可以控制了。

    可是呢,我边用边看API,发现一些很有趣的事,在获得返回内容的时候,URLConnection中竟然有两个方法,一个是Object getContent(),一个InputStream getInputStream()方法。当我直接输出返回值时,都为一个inputStream,当然,因为是JDK中最基本的,而且用的是socket,返回这个没什么。可返回都一样,为什么要有两个方法呢?想了好久没明白,后来再看API,发现其中有这样一个方法setContentHandlerFactory(ContentHandlerFactory fac),然后慢慢的看API后发现ContentHandlerFactory只是一个接口,而它只有一个方法ContentHandler  createContentHandler(String mimetype)。再跟ContentHandler ,发现它有两个方法Object getContent(URLConnection urlc)、Object getContent(URLConnection urlc,Class[] classes)。这样,终于明天了,getContent()实际上底层调用了这两个方法。应该来说,类似于监听器。

    那么,当我在请求HTML的时候,我只要实现自己的接口,然后再调用 setContentHandlerFactory方法,我就可以把返回和文本转换成String,不用每次都进行转换了。例如,我定义了一个实现类:

package content;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ContentHandler;
import java.net.ContentHandlerFactory;
import java.net.URLConnection;

public class ContentHandlerFactoryImpl implements ContentHandlerFactory {

	private static final String DEFAULT_ENCODING = "UTF-8";

	@Override
	public ContentHandler createContentHandler(String mimetype) {
		
		if (mimetype == null) {
			return new ContentHandlerImpl(false);
		}
		if (StringConfig.isStringType(mimetype)) {
			return new ContentHandlerImpl(true);
		} else {
			return new ContentHandlerImpl(false);
		}

	}

	class ContentHandlerImpl extends ContentHandler {

		private boolean transform = false;

		public ContentHandlerImpl(boolean transform) {
			this.transform = transform;
		}

		@Override
		public Object getContent(URLConnection connection) throws IOException {
			if (!transform) {
				return connection.getInputStream();
			} else {
				String encoding = getEncoding(connection.getHeaderField("Content-Type"));
				if (encoding == null) {
					encoding = DEFAULT_ENCODING;
				}
				
				BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), encoding));
				String temp = null;
				StringBuilder content = new StringBuilder();
				while ((temp = reader.readLine()) != null) {
					content.append(temp);
				}
				return content.toString();
			}
		}

		private String getEncoding(String contentType) {
			String[] headers = contentType.split(";");
			for (String header : headers) {
				String[] params = header.split("=");
				if (params.length == 2) {
					if (params[0].equals("charset")) {
						return params[1];
					}
				}
			}
			return null;
		}

	}

}
这里有一个配置文件,是自己定义的,不全,只是拿来测试的。

<?xml version="1.0" encoding="UTF-8"?>
<types>
	<mime-type>text/plain</mime-type>
	<mime-type>text/html</mime-type>
	<mime-type>text/css</mime-type>
	<mime-type>text/csv</mime-type>
	<mime-type>application/javascript</mime-type>
	<mime-type>application/json</mime-type>
	<mime-type>application/xml</mime-type>
</types>
这样的话,当返回的为HTML或其它非流的文件时,不再需要每次去写转换了。

你可能感兴趣的:(java,httpclient,urlconnection)