解决Android与服务器交互大容量数…
  Ts61YH3OBI3k 2023年11月02日 48 0


对于目前的状况来说,移动终端的网络状况没有PC网络状况那么理想。在一个Android应用中,如果需要接收来自服务器的大容量数据,那么就不得不考虑客户的流量问题。本文根据笔者的一个项目实战经验出发,解决大容量数据的交互问题,解决数据大小会根据实际情况动态切换问题(服务器动态选择是否要压缩数据,客户端动态解析数据是否是被压缩的),还有数据交互的编码问题。

 



解决Android与服务器交互大容量数…_服务器



1 package com.chenjun.utils.compress;
  2 
  3 import java.io.ByteArrayInputStream;
  4 import java.io.ByteArrayOutputStream;
  5 import java.io.InputStream;
  6 import java.io.OutputStream;
  7 import java.util.zip.GZIPInputStream;
  8 import java.util.zip.GZIPOutputStream;
  9 
 10 public class Compress {
 11     private static final int BUFFER_LENGTH = 400;
 12     
 13     
 14     //压缩字节最小长度,小于这个长度的字节数组不适合压缩,压缩完会更大
 15     public static final int BYTE_MIN_LENGTH = 50;
 16     
 17     
 18     //字节数组是否压缩标志位
 19     public static final byte FLAG_GBK_STRING_UNCOMPRESSED_BYTEARRAY = 0;
 20     public static final byte FLAG_GBK_STRING_COMPRESSED_BYTEARRAY = 1;
 21     public static final byte FLAG_UTF8_STRING_COMPRESSED_BYTEARRAY = 2;
 22     public static final byte FLAG_NO_UPDATE_INFO = 3;
 23     
 24       
 31     public static void compress(InputStream is, OutputStream os)   
 32             throws Exception {   
 33   
 34         GZIPOutputStream gos = new GZIPOutputStream(os);   
 35   
 36         int count;   
 37         byte data[] = new byte[BUFFER_LENGTH];   
 38         while ((count = is.read(data, 0, BUFFER_LENGTH)) != -1) {   
 39             gos.write(data, 0, count);   
 40         }   
 41   
 42         gos.finish();   
 43   
 44         gos.flush();   
 45         gos.close();   
 46     }   
 47     
 48     
 49       
 56     public static void decompress(InputStream is, OutputStream os)   
 57             throws Exception {   
 58   
 59         GZIPInputStream gis = new GZIPInputStream(is);   
 60   
 61         int count;   
 62         byte data[] = new byte[BUFFER_LENGTH];   
 63         while ((count = gis.read(data, 0, BUFFER_LENGTH)) != -1) {   
 64             os.write(data, 0, count);   
 65         }   
 66   
 67         gis.close();   
 68     } 
 69     
 70       
 77     public static byte[] byteCompress(byte[] data) throws Exception {  
 78         ByteArrayInputStream bais = new ByteArrayInputStream(data);  
 79         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
 80   
 81         // 压缩  
 82         compress(bais, baos);  
 83   
 84         byte[] output = baos.toByteArray();  
 85   
 86         baos.flush();  
 87         baos.close();  
 88   
 89         bais.close();  
 90   
 91         return output;  
 92     } 
 93     
 94     
 95       
102     public static byte[] byteDecompress(byte[] data) throws Exception {  
103         ByteArrayInputStream bais = new ByteArrayInputStream(data);  
104         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
105   
106         // 解压缩  
107   
108         decompress(bais, baos);  
109   
110         data = baos.toByteArray();  
111   
112         baos.flush();  
113         baos.close();  
114   
115         bais.close();  
116   
117         return data;  
118     }  
119 }


解决Android与服务器交互大容量数…_服务器



public ActionForward execute(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response) {
        JjjzForm jjjzForm = (JjjzForm) form;
        

        //基金净值历史走势信息
        ArrayList jjjzs = null;
        
        //得到基金净值历史走势的方法省略了
        
        Gson gson = new Gson();
        String jsonStr = gson.toJson(jjjzs, jjjzs.getClass());
        
        byte[] resultOriginalByte = jsonStr.getBytes();
                
        //组织最后返回数据的缓冲字节数组
        ByteArrayOutputStream resultBuffer = new ByteArrayOutputStream();
        OutputStream os = null;
        
        
        try {
            
            os = response.getOutputStream();
            //如果要返回的结果字节数组小于50位,不将压缩
            if(resultOriginalByte.length < Compress.BYTE_MIN_LENGTH){
                byte flagByte = Compress.FLAG_GBK_STRING_UNCOMPRESSED_BYTEARRAY;
                resultBuffer.write(flagByte);
                resultBuffer.write(resultOriginalByte);
            }
            else{
                byte flagByte = Compress.FLAG_GBK_STRING_COMPRESSED_BYTEARRAY;
                resultBuffer.write(flagByte);
                resultBuffer.write(Compress.byteCompress(resultOriginalByte));
            }
            resultBuffer.flush();
            resultBuffer.close();
                       
            //将最后组织后的字节数组发送给客户端
            os.write(resultBuffer.toByteArray());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally{
            try {
                os.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return null;
    }





解决Android与服务器交互大容量数…_服务器



byte[] receivedByte = EntityUtils.toByteArray(httpResponse.getEntity());

        String result = null;
        
        //判断接收到的字节数组是否是压缩过的
        if (receivedByte[0] == Compress.FLAG_GBK_STRING_UNCOMPRESSED_BYTEARRAY) {
            result = new String(receivedByte, 1, receivedByte.length - 1, EXCHANGE_ENCODING);
        } 
        
        else if (receivedByte[0] == Compress.FLAG_GBK_STRING_COMPRESSED_BYTEARRAY) {

            byte[] compressedByte = new byte[receivedByte.length - 1];

            for (int i = 0; i < compressedByte.length; i++) {
                compressedByte[i] = receivedByte[i + 1];
            }
            byte[] resultByte = Compress.byteDecompress(compressedByte);
            result = new String(resultByte, EXCHANGE_ENCODING);
        }



解决Android与服务器交互大容量数…_服务器





 这里最后得到的result就是服务器实际要发送的内容。

 缺陷反思:任何设计都是有缺陷的。我这样做已经将Http协议做了进一层封装。Http的数据部分的第一个字节并不是实际数据,而是标识字节。这样,降低了这个接口的可重用性。统一发送Json字符串的Action能被网页(Ajax)或者其他客户端使用,经过封装压缩之后,只有能识别这个封装(就是能进行解析)的客户端能使用这个接口。网页(Ajax)就不能解析,那么这个Action就不能被Ajax使用。

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
Ts61YH3OBI3k