在阅读后面的代码之前,建议您先阅读这篇文章,了解一下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<Byte> readGzipBody(InputStream is) throws IOException {
// 压缩块的大小,由于chunked编码块的前面是一个标识压缩块大小的16进制字符串,在开始读取前,需要获取这个大小
int chunk = getChunkSize(is);
List<Byte> bodyByteList = new ArrayList<Byte>();
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<Byte> tmpList = readGzipBody(is);
bodyByteList.addAll(tmpList);
}
return bodyByteList;
}
取出来后,把Byte数组转换为字符串就可以了,代码如下:
/**
* 获取没有压缩的消息体
*
* @param is
* @param contentLe
* @return
*/
private static String readBody(InputStream is, int contentLe) {
List<Byte> lineByteList = new ArrayList<Byte>();
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++的代码比较多。