用java发送Http请求,并对chunked解码的介绍

在阅读后面的代码之前,建议您先阅读这篇文章,了解一下chunked编码:

http://blog.csdn.net/whatday/article/details/7571451


简单介绍:

chunked的编码是吧整个压缩包分段传输,其实有点像我们把压缩包压缩时分成若干个压缩文件一样,解压的时候,必须把全部文件放到一个目录下解压缩。

这个编码也是如此,传过来的是一个一个块,最后需要把这些块都拼接起来才是完整的数据,所以,只要一次把这些块取出来拼到一块就可以了。


如何取:

chunked编码在压缩块前面都会有一个标识压缩块大小的16进制字符串,我们每次读取压缩块之前,需要先获得这个大小,以便告诉程序接下来该读取多少数据,下面一段代码就是获取这个值。

    /**
     * 获取压缩包块的大小
     * 
     * @param is
     * @return
     * @throws IOException
     */
	private static int getChunkSize(InputStream is) throws IOException {
		String sLength = readLine(is).trim();
		if (isBlank(sLength)) {  // 字符串前面有可能会是一个回车换行。
			// 读了一个空行,继续往下读取一行。
			sLength = readLine(is).trim();
		}
        if (sLength.length() < 4) {
        	sLength = 0 + sLength;
        }
        // 把16进制字符串转化为Int类型
        int length = Integer.valueOf(sLength, 16);
        return length;
	}

有了这个大小以后,就很容易获取后面的数据了,下面这段代码是读取块的数据,并进行递归:

	/**
	 * 读取gzip压缩的消息体
	 * 
	 * @param is
	 * @return
	 * @throws IOException
	 */
    private static List readGzipBody(InputStream is) throws IOException {
    	// 压缩块的大小,由于chunked编码块的前面是一个标识压缩块大小的16进制字符串,在开始读取前,需要获取这个大小
    	int chunk = getChunkSize(is);
    	List bodyByteList = new ArrayList();
        byte readByte = 0;
        int count = 0;
        
        while (count < chunk) {  // 读取消息体,最多读取chunk个byte
            readByte = (byte) is.read();  
            bodyByteList.add(Byte.valueOf(readByte));
            count ++;
        }
        if (chunk > 0) { // chunk为读取到最后,如果没有读取到最后,那么接着往下读取。
        	List tmpList = readGzipBody(is);
        	bodyByteList.addAll(tmpList);
        }
        return bodyByteList;
    }
	

取出来后,把Byte数组转换为字符串就可以了,代码如下:

	/**
	 * 获取没有压缩的消息体
	 * 
	 * @param is
	 * @param contentLe
	 * @return
	 */
	private static String readBody(InputStream is, int contentLe) {
		List lineByteList = new ArrayList();  
        byte readByte;  
        int total = 0; 
        try {
			do {  
				readByte = (byte) is.read();
	            lineByteList.add(Byte.valueOf(readByte));  
	            total++;  
	        } while (total < contentLe);
		} catch (IOException e) {
			e.printStackTrace();
		}  
        
        byte[] tmpByteArr = new byte[lineByteList.size()];  
        for (int i = 0; i < lineByteList.size(); i++) {  
            tmpByteArr[i] = ((Byte) lineByteList.get(i)).byteValue();  
        }  
        lineByteList.clear();  
  
        String line = "";
		try {
			line = new String(tmpByteArr, encoding);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		
		return line;
	}


主要的就这几个方法。

完整的代码可以到csdn里下载,见下面连接:

http://download.csdn.net/detail/lhj_5460/9069945

供大家参考,或者不是最好的方案,希望对大家有帮助。

写这段代码废了老大劲,java的代码没有找到有,大多数都是c,获取c++的代码比较多。


你可能感兴趣的:(Java文章)