1. 程式人生 > >【Android】TVL資料流解析

【Android】TVL資料流解析

tlv資料格式:type(1位元組)+length(2位元組)+value(有效資料);

長度規定(雙方規定的):{低位、高位}   ,例:{(byte)0x5A,(byte)0x00} 轉成int = 0x005A = 90 ;

package com.example.util;

import android.util.Log;

import java.io.IOException;
import java.io.InputStream;

/**
 * @author alan
 *         Created by Administrator on 2018/4/8 0008.
 */
public class TLVUtil {

    public interface CallBack {
        void getValue(String valueData);
    }

    ;


    /**
     * 從TLV格式資料流解析出中的value
     *
     * @param inputStream
     */
    public void parseValueFromTLVInputStream(InputStream inputStream, CallBack callBack) throws Exception {
        try {
            boolean isOnce = true;//開始一次tlv資料讀取
            StringBuilder builder = new StringBuilder();
            int leftPartSize = 0;//剩餘長度
            while (true) {
                Thread.sleep(50);
                if (inputStream == null) return;

                if (inputStream.available() > 0) {//收到一次推送的資料
                    byte[] valueArray;
                    int available = inputStream.available();

                    //繼續讀取value(上次tlv不完整)
                    if (!isOnce) {

//                        byte[] buf = new byte[leftPartSize];
//                        int len = inputStream.read(buf);
//                        String part = new String(buf, 0, len);
//                        builder.append(part);

                        if (leftPartSize > available) {//剩下已知的 > 讀取的,還需要繼續讀取
                            leftPartSize = leftPartSize - available;

                            //取vaule資料
                            valueArray = new byte[available];
                            int read = inputStream.read(valueArray);
                            String valueStr = new String(valueArray, 0, read);
                            builder.append(valueStr);
                            continue;
                        } else {//剩下已知的 =< 讀取的
                            //拆分出最後已知的
                            valueArray = new byte[leftPartSize];
                            int read = inputStream.read(valueArray);
                            String valueStr = new String(valueArray, 0, read);
                            // 組成完整value
                            builder.append(valueStr);
                            String allValue = builder.toString();
                            builder = new StringBuilder();//清空
                            //<處理>
                            callBack.getValue(allValue);

                            //開始下次tlv處理
                            isOnce = true;
                            available = available - leftPartSize;
                            leftPartSize = 0;
                            builder = new StringBuilder();//清空

                            if (available == 0) {//沒資料了,重新讀流
                                continue;
                            }
                            Log.e("TAG", "下次tlv處理-available->" + available);

                        }

                    }

                    //tlv處理
                    while (isOnce) {
                        //取type
                        byte[] typeArray = new byte[1];
                        inputStream.read(typeArray);
                        int type = (typeArray[0] & 0xff);//第一個位元組表示type(byte轉int)
                        //取length(2位元組)
                        byte[] lengthArray = new byte[2];
                        inputStream.read(lengthArray);
                        int length = bytesTolength(lengthArray);

                        Log.e("TAG", "tlv-length->" + length);


                        //判斷
                        if (available > (length + 3)) {//推過來的 》已知的 ,繼續讀剩下新的tlv
                            isOnce = true;
                            leftPartSize = available - (length + 3);
                            available = leftPartSize;

                            //取vaule資料(完整)
                            valueArray = new byte[length];
                            int read = inputStream.read(valueArray);
                            String valueStr = new String(valueArray, 0, read);
//                            builder.append(valueStr);
                            //<處理>
                            callBack.getValue(valueStr);


                        } else if (available == (length + 3)) {
                            isOnce = true;

                            //取vaule資料(完整)
                            valueArray = new byte[length];
                            int read = inputStream.read(valueArray);
                            String valueStr = new String(valueArray, 0, read);
//                            builder.append(valueStr);
                            //<處理>
                            callBack.getValue(valueStr);

                            break;
                        } else {//available < (length + 3) 讀取不完整,需要繼續讀取
                            isOnce = false;
                            leftPartSize = (length + 3) - available;

                            //取vaule資料(不完整)
                            valueArray = new byte[available - 3];
                            int read = inputStream.read(valueArray);
                            String valueStr = new String(valueArray, 0, read);
                            builder.append(valueStr);
                            break;
                        }
                    }//end while-isOnce


                }

            }
        } catch (IOException e) {
            e.printStackTrace();
            Log.e("TAG", "client connected name--->" + Thread.currentThread().getName() + "  e-->" + e.getMessage());
//            Log.e("TAG", "異常-tlv解析->" + e.getMessage());
        }
    }

    /**
     * byte陣列轉長度值 {低位,高位} [參照文件規定]
     *
     * @param array
     * @return
     */
    public int bytesTolength(byte[] array) {
        int length = 0;
        if (array != null) {
            length = ((array[0] & 0xff))
                    | ((array[1] & 0xff) << 8);
        }
        return length;
    }
}