使用HttpUrlConnection获取数据,Unicode和GZIPInputStream的坑

在不使用第三方库的Android开发中,使用HttpURLConnection获取数据时可能会遇到GZIPInputStream和Unicode编码问题。GZIPInputStream导致的乱码可以通过设置请求属性和解压操作解决;Unicode问题则需要进行特定的解码处理。虽然OkHttp框架可以自动处理GZIP,但仍需关注Unicode解码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于HTTP的报文头设置,作为一名Android开发者,如果在没有使用第三方框架的前提条件下,直接使用HttpUrlConnection进行GET数据,会因为参数属性的设置导致一些不必要的麻烦。本文主要是我在裸辞后,找工作时,公司给的测试题,在使用HttpURLConnection访问数据时挖出的坑。共有两个大方向的BUG。一是GZIPInputStream,另一个是Unicode。
一、GZIPInputStream问题。
在成功获取数据之后,通过打印,发现出现乱码问题,排除两端的utf-8编码,依旧是乱码,在调试过程中,发现conn.getInputStream()返回的对象是GZIPInputStream。这在之前公司和个人项目中从未有过,所以去百度。
解决办法:
1:设定请求属性——

    conn.setRequestProperty("Accept-Encoding", "gzip, deflate");

2:在返回时做解压操作——

   String content_encode = conn.getContentEncoding();
            if (null != content_encode && !"".equals(content_encode) && content_encode.contains("gzip")) {
                GZIPInputStream in = new GZIPInputStream(is);
                if (in == null) {
                    return "";
                }

第一个步骤必须有,否则conn.getContentEncoding()的值只会是NULL.

二、Unicode问题。
在浏览器中访问,返回JSON字符串中中文不是中文,当时以为还是乱码问题,通过和公司接口提供人员沟通,确定是Unicode编码问题,也就是说需要做解码,该解码的函数是本人在网络上找的,验证正确:


    public static String decodeUnicode(String theString) {
        char aChar;
        int len = theString.length();
        StringBuffer outBuffer = new StringBuffer(len);
        for (int x = 0; x < len;) {
            aChar = theString.charAt(x++);
            if (aChar == '\\') {
                aChar = theString.charAt(x++);
                if (aChar == 'u') {
                    // Read the xxxx
                    int value = 0;
                    for (int i = 0; i < 4; i++) {
                        aChar = theString.charAt(x++);
                        switch (aChar) {
                            case '0':
                            case '1':
                            case '2':
                            case '3':
                            case '4':
                            case '5':
                            case '6':
                            case '7':
                            case '8':
                            case '9':
                                value = (value << 4) + aChar - '0';
                                break;
                            case 'a':
                            case 'b':
                            case 'c':
                            case 'd':
                            case 'e':
                            case 'f':
                                value = (value << 4) + 10 + aChar - 'a';
                                break;
                            case 'A':
                            case 'B':
                            case 'C':
                            case 'D':
                            case 'E':
                            case 'F':
                                value = (value << 4) + 10 + aChar - 'A';
                                break;
                            default:
                                throw new IllegalArgumentException(
                                        "Malformed   \\uxxxx   encoding.");
                        }

                    }
                    outBuffer.append((char) value);
                } else {
                    if (aChar == 't')
                        aChar = '\t';
                    else if (aChar == 'r')
                        aChar = '\r';
                    else if (aChar == 'n')
                        aChar = '\n';
                    else if (aChar == 'f')
                        aChar = '\f';
                    outBuffer.append(aChar);
                }
            } else
                outBuffer.append(aChar);
        }
        return outBuffer.toString();
    }

成功解决问题后,最终本人使用OkHttp框架来进行另一个接口的测试,当时公司一共给了两个接口来作为应聘的测试题目。在使用过程中,发现在使用该框架的情况下,不需要考虑GZIPInputStream的问题,但是依旧需要做Unicode的解码工作。

  String mUrl = sb.toString();
        OkHttpClient mOkHttpClient = new OkHttpClient();
        Request request = new Request.Builder().url(mUrl).build();
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

                String responseData = response.body().string();
                String data = HttpRequestInternet.decodeUnicode(responseData);
                if (data.length() < 1){
                    return;
                }
                if (!data.endsWith("}")){
                    int length = data.length();
                    int len = data.lastIndexOf(",");
                    String dataDeal = data.substring(0, len) + "}";
                    setResponseData(dataDeal);
                    newsInterface.updateUI(responseData);

                } else{
                    setResponseData(data);
                    newsInterface.updateUI(responseData);
                }
            }
        });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值