waysun一路陽光

          不輕易服輸,不輕言放棄.--心是夢的舞臺,心有多大,舞臺有多大。踏踏實實做事,認認真真做人。

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 ::  :: 管理 ::
            167 隨筆 :: 1 文章 :: 64 評論 :: 0 Trackbacks

          前段時間做了一個涉及到IS08583報文協(xié)議的項目,自己總結(jié)寫了這篇附有java源代碼的文章,希望能給大家提供一些幫助,本文分四個部分介紹IS08583報文協(xié)議包的處理及如何解析請求包及怎樣封裝返回包,

          一:IS08583包介紹:

               ISO8583包(簡稱8583包)是一個國際標準的包格式,最多由128個字段域組成,每個域都有統(tǒng)一的規(guī)定,并有定長與變長之分。
               8583包前面一段為位圖,用來確定包的字段域組成情況。其中位圖是8583包的靈魂,它是打包解包確定字段域的關鍵, 而了解每個字段域的屬性則是填寫數(shù)據(jù)的基礎。   

           1:位圖說明:

               位置:在8583包的第1 位
               格式:定長  
               類型:B16(二進制16位,16*8=128bit)  
               描述:  
               如將位圖的第一位設為'1',表示使用擴展位圖(128個域),否則表示只使用基本位圖(64個域)。  
               如使用某數(shù)據(jù)域,應在位圖中將相應的位設位'1',如使用41域,需將位圖的41位設為'1'。  
               選用條件:如使用65到128域,需設位圖域第一位為'1'  
          2:域的定義:  
          typedef struct ISO8583  
          {  
              int bit_flag;            /*域數(shù)據(jù)類型0 -- string, 1 -- int, 2 -- binary*/  
              char *data_name;  /*域名*/  
              int length;             /*數(shù)據(jù)域長度*/  
              int length_in_byte;/*實際長度(如果是變長)*/  
              int variable_flag;   /*是否變長標志0:否 2:2位變長, 3:3位變長*/  
              int datatyp;         /*0 -- string, 1 -- int, 2 -- binary*/  
              char *data;         /*存放具體值*/  
              int attribute;      /*保留*/  
          } ISO8583;

          二:定義BitMap類

          類說明:根據(jù)ISO8583 包的域定義,定義BitMap類存儲每個域的信息。例如:

          package com.lottery.pos.model;

          public  class BitMap {
           private int bit; //位
           private int bittype; //數(shù)據(jù)類型 1 ascii 2 binary
           private int variable;  //是否變長0 不是 2 兩位變長 3 三位變長
           private int len; //數(shù)據(jù)長度
           private byte[] dat; //數(shù)據(jù)
           
           public int getBit() {
            return bit;
           }
           public void setBit(int bit) {
            this.bit = bit;
           }
           public int getBittype() {
            return bittype;
           }
           public void setBittype(int bittype) {
            this.bittype = bittype;
           }
           public int getVariable() {
            return variable;
           }
           public void setVariable(int variable) {
            this.variable = variable;
           }
           public byte[] getDat() {
            return dat;
           }
           public void setDat(byte[] dat) {
            this.dat = dat;
           }
           public int getLen() {
            return len;
           }
           public void setLen(int len) {
            this.len = len;
           }


          }

           

          三:定義PortConfig類

          類說明:定義配置信息類。根據(jù)此類解析和封裝數(shù)據(jù)。例如:

          package com.lottery.pos.model;

          public class PortConfig {
           /**
            * 存放所有接口的配置信息
            * [][0] bit     位:在Map中的位
            * [][1] type   類型:1 ascii 2 binary
            * [][2] len    長度:(對定長有效)
            * [][3] varLen 變長:0非變長 2位變長 3位變長
            */
           // 定義一個二位數(shù)組存放配置信息。
           public static final  int[][] config= {
             {11,1,6,0},
             {12,1,6,0},
             {13,1,4,0},
             {32,1,11,0},
             {37,1,12,0},
             {39,1,2,0},
             {40,2,50,2},
             {41,1,8,0},
             {48,1,52,3},
             {120,2,128,3},
             };

          四:定義BitMapiso類

          類說明:此類提供解析請求包和封裝信息包兩個方法,例如:

          package com.lottery.pos.utils;

          import java.util.ArrayList;
          import java.util.List;

          import com.lottery.pos.model.BitMap;

          public class BitMapiso {

           /**
            * 解析請求包
            * @param body
            * @param config
            * @return List
            */
           @SuppressWarnings("unchecked")
           public static List unpackRequest(byte[] body, int[][] config) {
            List outList = new ArrayList();
            // 取得除信息類型以外的包信息。也就是取得位圖的初始位置。
            byte[] realbody = new byte[body.length - 4];
            System.arraycopy(body, 4, realbody, 0, realbody.length);
            // 取得位圖
            byte[] map = null;
            byte[] map8 = new byte[8];
            System.arraycopy(realbody, 0, map8, 0, 8);
            boolean[] bmap8 = LoUtils.getBinaryFromByte(map8);
            if (bmap8[1]) {
            // 如果第一位為1,則是可擴展位圖,設為16字節(jié)長度。
             map = new byte[16];
             System.arraycopy(realbody, 0, map, 0, 16);
            } else {
             map = map8;
            }
            boolean[] bmap = LoUtils.getBinaryFromByte(map);

            int tmplen = map.length;
            for (int i = 2; i < bmap.length; i++) {
             if (bmap[i]) {
              //BitMap bitMap = null;
              // 尋找位圖中的1對應的數(shù)據(jù)
              int bit=-1;
              for (int j = 0; j < config.length; j++) {
               if (config[j][0] == i) {
                bit=j;
                break;
               }
              }
              BitMap outBitMap = new BitMap();
              outBitMap.setBit(i);
              outBitMap.setBittype(config[bit][1]);
              //len對變長是無用的。
              outBitMap.setLen(config[bit][2]);
              outBitMap.setVariable(config[bit][3]);
              byte[] nextData = null;
              if (config[bit][3] > 0) {
               //取出變長部分的值。
               int varLen = config[bit][3];
               if (config[bit][1] == 2) {
                varLen = varLen - 1;
               }
               byte[] varValue = new byte[varLen];
               System.arraycopy(realbody, tmplen, varValue, 0, varValue.length);
               int datLen = 0;
               if (config[bit][1] == 2) {
                datLen = LoUtils.bcdToint(varValue);
               } else {
                datLen = byteToInt(varValue);
               }

               tmplen += varLen;
               // 取出變長部分后帶的值。
               nextData = new byte[datLen];

               System.arraycopy(realbody, tmplen, nextData, 0,nextData.length);
               tmplen += nextData.length;
              } else {
               nextData = new byte[config[bit][2]];
               System.arraycopy(realbody, tmplen, nextData, 0,nextData.length);
               tmplen += config[bit][2];
              }
              outBitMap.setDat(nextData);
              outList.add(outBitMap);
             }
            }

            return outList;
           }

           

           /**
            * 打包響應包,不包括消息類型
            * @param list
            * @return byte[]
            */
           @SuppressWarnings("unchecked")
           public static byte[] PackResponse(List list) {
            int len = 16;
            for (int i = 0; i < list.size(); i++) {
             BitMap bitMap = (BitMap) list.get(i);
             // 計算請求包總長度
             if (bitMap.getBittype() == 2) {
              if (bitMap.getVariable() > 0) {
               len += bitMap.getVariable() - 1 + bitMap.getDat().length;
              } else {
               len += bitMap.getVariable() + bitMap.getDat().length;
              }
             } else {
              len += bitMap.getVariable() + bitMap.getDat().length;
             }
            }
            byte[] body = new byte[len];
            // 位圖
            boolean[] bbitMap = new boolean[129];
            bbitMap[1] = true;
            int temp = (bbitMap.length - 1) / 8;
            for (int j = 0; j < list.size(); j++) {
             BitMap bitMap = (BitMap) list.get(j);
             bbitMap[bitMap.getBit()] = true;
             byte[] bitmap = LoUtils.getByteFromBinary(bbitMap);
             System.arraycopy(bitmap, 0, body, 0, bitmap.length);
             // 數(shù)據(jù)
             if (bitMap.getVariable() > 0) {
              // 數(shù)據(jù)是可變長的:拼變長的值
              byte[] varValue = null;
              if (bitMap.getBittype() == 2) {
               varValue = LoUtils.StrToBCDBytes(String.format("%0"+ bitMap.getVariable() + "d",bitMap.getDat().length));
              } else {
               varValue = String.format("%0" + bitMap.getVariable() + "d",bitMap.getDat().length).getBytes();
              }
              System.arraycopy(varValue, 0, body, temp, varValue.length);
              temp += varValue.length;
              // 拼變長部分后所帶的數(shù)的值。
              System.arraycopy(bitMap.getDat(), 0, body, temp, bitMap.getDat().length);
              temp += bitMap.getDat().length;
             } else {
              // 數(shù)據(jù)是固定長度的。
              byte dat[] =new byte[bitMap.getLen()];
              if (bitMap.getDat().length!=bitMap.getLen()){     
               System.arraycopy(bitMap.getDat(), 0, dat, 0, bitMap.getLen());
              }else{
               dat=bitMap.getDat();
              } 
              System.arraycopy(dat, 0, body, temp, dat.length);
              temp += bitMap.getDat().length;
             }
            }
            return body;
           }

           

           

           

          package com.lottery.utils;

          import java.io.BufferedInputStream;
          import java.io.ByteArrayOutputStream;
          import java.io.IOException;

          import javax.servlet.http.HttpServletRequest;

          import sun.misc.BASE64Decoder;
          import sun.misc.BASE64Encoder;

          /**
           * 編碼與數(shù)據(jù)類型類
           *
           * @author LLH
           */
          public class LoUtils
          {
           private static BASE64Encoder encoder = new BASE64Encoder ();
           private static BASE64Decoder decoder = new BASE64Decoder ();
           
           /**
            * BASE64 編碼
            *
            * @param s
            * @return
            */
           public static String encodeBufferBase64(byte [] buff)
           {
            return buff == null ? null : encoder.encode (buff);
           }
           
           /**
            * BASE64解碼
            *
            * @param s
            * @return
            */
           public static byte [] decodeBufferBase64(String s)
           {
            try
            {
             return s == null ? null : decoder.decodeBuffer (s);
            }catch (IOException e)
            {
             e.printStackTrace ();
            }
            return null;
           }
           
           /**
            * BASE64 字節(jié)數(shù)組編碼
            *
            * @param s
            * @return String
            */
           public static String encodeBase64(byte [] s)
           {
            if(s == null)
             return null;
            String res = new BASE64Encoder ().encode (s);
            res = res.replace ("\n","");
            res = res.replace ("\r","");
            return res;
           }
           
           /**
            * BASE64解碼
            *
            * @param s
            * @return
            */
           public static byte [] decodeBase64(byte [] buff)
           {
            if(buff == null)
             return null;
            BASE64Decoder decoder = new BASE64Decoder ();
            try
            {
             byte [] b = decoder.decodeBuffer (new String (buff));
             
             return b;
            }catch (Exception e)
            {
             return null;
            }
           }
           
           /**
            * 將reauest里的數(shù)據(jù)包轉(zhuǎn)成字符串
            *
            * @param request
            * @return String
            */
           public static String getRequestBodyTxt(HttpServletRequest request)
           {
            // 接收手機傳過來的參數(shù)
            BufferedInputStream bufferedInputStream = null;
            // 此類實現(xiàn)了一個輸出流,其中的數(shù)據(jù)被寫入一個字節(jié)數(shù)組
            ByteArrayOutputStream bytesOutputStream = null;
            String body = null;
            try
            {
             
             // BufferedInputStream 輸入流
             bufferedInputStream = new BufferedInputStream (
              request.getInputStream ());
             bytesOutputStream = new ByteArrayOutputStream ();
             // 寫入數(shù)據(jù)
             int ch;
             while ((ch = bufferedInputStream.read ()) != -1)
             {
              bytesOutputStream.write (ch);
             }
             // 轉(zhuǎn)換為String類型
             body = new String (bytesOutputStream.toByteArray (),"UTF-8");
            }catch (Exception ex)
            {
             ex.printStackTrace ();
            }
            finally
            {
             // 關閉此輸入流并釋放與該流關聯(lián)的所有系統(tǒng)資源。
             try
             {
              bytesOutputStream.flush ();
              bytesOutputStream.close ();
              bufferedInputStream.close ();
             }catch (IOException e)
             {
              e.printStackTrace ();
             }
            }
            return body;
           }
           
           /**
            * 將reauest里的數(shù)據(jù)包轉(zhuǎn)成字節(jié)數(shù)組
            *
            * @param request
            * @return
            */
           public static byte [] getRequestBodyByte(HttpServletRequest request)
           {
            // 接收手機傳過來的參數(shù)
            BufferedInputStream bufferedInputStream = null;
            // 此類實現(xiàn)了一個輸出流,其中的數(shù)據(jù)被寫入一個字節(jié)數(shù)組
            ByteArrayOutputStream bytesOutputStream = null;
            byte [] body = null;
            try
            {
             // BufferedInputStream 輸入流
             bufferedInputStream = new BufferedInputStream (
              request.getInputStream ());
             bytesOutputStream = new ByteArrayOutputStream ();
             // 寫入數(shù)據(jù)
             int ch;
             while ((ch = bufferedInputStream.read ()) != -1)
             {
              bytesOutputStream.write (ch);
             }
             // 轉(zhuǎn)換為String類型
             body = bytesOutputStream.toByteArray ();
            }catch (Exception ex)
            {
             ex.printStackTrace ();
            }
            finally
            {
             // 關閉此輸入流并釋放與該流關聯(lián)的所有系統(tǒng)資源。
             try
             {
              bytesOutputStream.flush ();
              bytesOutputStream.close ();
              bufferedInputStream.close ();
             }catch (IOException e)
             {
              e.printStackTrace ();
             }
            }
            return body;
           }
           
           public static String getEigthBitsStringFromByte(int b)
           {
            // if this is a positive number its bits number will be less
            // than 8
            // so we have to fill it to be a 8 digit binary string
            // b=b+100000000(2^8=256) then only get the lower 8 digit
            b |= 256; // mark the 9th digit as 1 to make sure the string
            // has at
            // least 8 digits
            String str = Integer.toBinaryString (b);
            int len = str.length ();
            return str.substring (len - 8,len);
           }
           
           public static byte getByteFromEigthBitsString(String str)
           {
            // if(str.length()!=8)
            // throw new Exception("It's not a 8 length string");
            byte b;
            // check if it's a minus number
            if(str.substring (0,1).equals ("1"))
            {
             // get lower 7 digits original code
             str = "0" + str.substring (1);
             b = Byte.valueOf (str,2);
             // then recover the 8th digit as 1 equal to plus
             // 1000000
             b |= 128;
            }
            else
            {
             b = Byte.valueOf (str,2);
            }
            return b;
           }
           
           /**
            * 將一個16字節(jié)數(shù)組轉(zhuǎn)成128二進制數(shù)組
            *
            * @param b
            * @return
            */
           public static boolean [] getBinaryFromByte(byte [] b)
           {
            boolean [] binary = new boolean [b.length * 8 + 1];
            String strsum = "";
            for (int i = 0;i < b.length;i++ )
            {
             strsum += getEigthBitsStringFromByte (b [i]);
            }
            for (int i = 0;i < strsum.length ();i++ )
            {
             if(strsum.substring (i,i + 1).equalsIgnoreCase ("1"))
             {
              binary [i + 1] = true;
             }
             else
             {
              binary [i + 1] = false;
             }
            }
            return binary;
           }
           
           /**
            * 將一個128二進制數(shù)組轉(zhuǎn)成16字節(jié)數(shù)組
            *
            * @param binary
            * @return
            */
           public static byte [] getByteFromBinary(boolean [] binary)
           {
            
            int num = (binary.length - 1) / 8;
            if((binary.length - 1) % 8 != 0)
            {
             num = num + 1;
            }
            byte [] b = new byte [num];
            String s = "";
            for (int i = 1;i < binary.length;i++ )
            {
             if(binary [i])
             {
              s += "1";
             }
             else
             {
              s += "0";
             }
            }
            String tmpstr;
            int j = 0;
            for (int i = 0;i < s.length ();i = i + 8)
            {
             tmpstr = s.substring (i,i + 8);
             b [j] = getByteFromEigthBitsString (tmpstr);
             j = j + 1;
            }
            return b;
           }
           
           /**
            * 將一個byte位圖轉(zhuǎn)成字符串
            *
            * @param b
            * @return
            */
           public static String getStrFromBitMap(byte [] b)
           {
            String strsum = "";
            for (int i = 0;i < b.length;i++ )
            {
             strsum += getEigthBitsStringFromByte (b [i]);
            }
            return strsum;
           }
           
           /**
            * bytes轉(zhuǎn)換成十六進制字符串
            *
            * @param b
            * @return
            */
           public static String byte2HexStr(byte [] b)
           {
            String hs = "";
            String stmp = "";
            for (int n = 0;n < b.length;n++ )
            {
             stmp = (Integer.toHexString (b [n] & 0XFF));
             if(stmp.length () == 1)
              hs = hs + "0" + stmp;
             else
              hs = hs + stmp;
            }
            return hs.toUpperCase ();
           }
           
           private static byte uniteBytes(String src0, String src1)
           {
            byte b0 = Byte.decode ("0x" + src0).byteValue ();
            b0 = (byte) (b0 << 4);
            byte b1 = Byte.decode ("0x" + src1).byteValue ();
            byte ret = (byte) (b0 | b1);
            return ret;
           }
           
           /**
            * 十六進制字符串轉(zhuǎn)換成bytes
            *
            * @param src
            * @return
            */
           public static byte [] hexStr2Bytes(String src)
           {
            int m = 0, n = 0;
            int l = src.length () / 2;
            byte [] ret = new byte [l];
            for (int i = 0;i < l;i++ )
            {
             m = i * 2 + 1;
             n = m + 1;
             ret [i] = uniteBytes (src.substring (i * 2,m),
              src.substring (m,n));
            }
            return ret;
           }
           
           /**
            * 將String轉(zhuǎn)成BCD碼
            *
            * @param s
            * @return
            */
           public static byte [] StrToBCDBytes(String s)
           {
            
            if(s.length () % 2 != 0)
            {
             s = "0" + s;
            }
            ByteArrayOutputStream baos = new ByteArrayOutputStream ();
            char [] cs = s.toCharArray ();
            for (int i = 0;i < cs.length;i += 2)
            {
             int high = cs [i] - 48;
             int low = cs [i + 1] - 48;
             baos.write (high << 4 | low);
            }
            return baos.toByteArray ();
           }
           
           /**
            * 將BCD碼轉(zhuǎn)成int
            *
            * @param b
            * @return
            */
           public static int bcdToint(byte [] b)
           {
            StringBuffer sb = new StringBuffer ();
            for (int i = 0;i < b.length;i++ )
            {
             int h = ((b [i] & 0xff) >> 4) + 48;
             sb.append ((char) h);
             int l = (b [i] & 0x0f) + 48;
             sb.append ((char) l);
            }
            return Integer.parseInt (sb.toString ());
           }
           
           /**
            * 輸出調(diào)試信息
            *
            * @param str
            */
           public static void trace(String str)
           {
          //  System.out.println ("["
          //   + (new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss.S")).format (new Date ())
          //   + "]>" + str);
           }
          }

           

           

          源代碼測試沒有問題。

          posted on 2011-06-20 14:58 weesun一米陽光 閱讀(3702) 評論(1)  編輯  收藏

          評論

          # re: IS08583報文協(xié)議包的解析和封裝java源代碼 【轉(zhuǎn)】 2013-08-08 10:32 九十度
          你好,可以把源代碼發(fā)一份給我嗎,172581565@qq.com  回復  更多評論
            


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導航:
           
          主站蜘蛛池模板: 襄垣县| 田阳县| 芷江| 年辖:市辖区| 资讯 | 神木县| 湘潭县| 武威市| 理塘县| 老河口市| 株洲市| 黎川县| 惠安县| 林芝县| 浦北县| 固镇县| 宜兰县| 靖远县| 竹溪县| 朝阳区| 安阳市| 洱源县| 松阳县| 青神县| 抚宁县| 石狮市| 金溪县| 泌阳县| 措勤县| 江孜县| 正宁县| 辽宁省| 敦化市| 行唐县| 星座| 邻水| 海阳市| 彭水| 米脂县| 钟山县| 绍兴市|