ISO8583报文工具类(组装和解析报文)
很久没来csdn了。现在的工作地点在银行,妈的,不让上网啊。
写写博客其实是对自己知识的总结,这么长时间了,也该写点东西了。接触银行的项目,避免不了
遇上8583报文。具体介绍就不细讲了,这个网上一大堆介绍的。关键是怎么去组装和解析8583报文?
这个代码还真不好找。在此,我把自己的研究写成一个工具类,看的懂其实很好改写,看不懂就直接拿去用吧。
001 | package com.lsy.common.util; |
002 | |
003 | import java.io.FileInputStream; |
004 | import java.io.UnsupportedEncodingException; |
005 | import java.util.HashMap; |
006 | import java.util.Iterator; |
007 | import java.util.Map; |
008 | import java.util.Properties; |
009 | import java.util.TreeMap; |
010 | |
011 | /** |
012 | * |
013 | * 这是本人写的ISO8583报文工具类,包含了报文的组装和解析。 |
014 | * |
015 | * 简单介绍下ISO8583。 |
016 | * 这个东西说白了就是一种数据结构。我们定义一种规则把一堆东西放进去,再按照规则 |
017 | * 把数据正确拿出来。这就是报文的实质。 |
018 | * |
019 | * ISO8583报文的结构是:前面有16字节(128位)位图数据,后面就是数据。 |
020 | * 报文最多有128个域(字段)。具体的一个报文不会有这么多,一般是几个域。 |
021 | * 有哪几个就记录在位图中。而且域有定长和变长之分。 |
022 | * 这些都是事先定义好的,具体可以看我写的properties定义文件. |
023 | * |
024 | * 位图转化成01字符串就是128个,如果某一位是1,代表这个域有值,然后按照properties定义的规则取值。 |
025 | * 如果是0,则这个域没有值。 |
026 | * |
027 | * 再说定长和变长。 |
028 | * 定长域(定长比较好理解,一个字段规定是N位,那么字段值绝对不能超过N位,不足N位就在后面补空格) |
029 | * 变长域(变长域最后组装成的效果:例如变长3位,定义var3,这里的3是指长度值占3位,字段值是123456,最后结果就是006123456) |
030 | * 注意(变长的长度按照域值得字节长度计算,而不是按照域值字符串长度算!) |
031 | * |
032 | * 从网上不难找到ISO8583报文的介绍,这里就不多说了。 |
033 | * 但是具体解析和组装的代码还真不好找,所以本人就写了一个让刚接触ISO8583报文的人更好入门。 |
034 | * |
035 | * |
036 | * |
037 | * 解析的容器,我使用了Map,具体到工作中,还是要换成其他的容器的。 |
038 | * 报文定义说明:config_8583.properties |
039 | * 例如 |
040 | * FIELD031 = string,10 |
041 | * FIELD032 = string,VAR2 |
042 | * |
043 | * FIELD031是定长,长度是10 |
044 | * FIELD032是变长,长度值占2位,也就是说长度值最大99,也就是域值最大长度99. |
045 | * |
046 | * @author lushuaiyin |
047 | * |
048 | */ |
049 | public class Lsy8583Util { |
050 | |
051 | public static String packet_encoding= "UTF-8" ; //报文编码 UTF-8 GBK |
052 | private static Map map8583Definition = null ; // 8583报文128域定义器 |
053 | |
054 | static { |
055 | String basepath=Lsy8583Util. class .getClassLoader().getResource( "" ).getPath(); |
056 | System.out.println(basepath); |
057 | System.out.println( "Lsy8583Util使用编码配置:[encoding:" +packet_encoding+ "]" ); |
058 | Properties property = new Properties(); |
059 | String path = basepath+ "/config_8583.properties" ; |
060 | FileInputStream fis; |
061 | try { |
062 | fis = new FileInputStream(path); |
063 | property.load(fis); |
064 | Lsy8583Util.map8583Definition = new HashMap(property); |
065 | fis.close(); |
066 | } catch (Exception e) { |
067 | e.printStackTrace(); |
068 | } |
069 | } |
070 | // 8583报文初始位图:128位01字符串 |
071 | public static String getInitBitMap(){ |
072 | String initBitMap = |
073 | "10000000" + "00000000" + "00000000" + "00000000" |
074 | + "00000000" + "00000000" + "00000000" + "00000000" |
075 | + "00000000" + "00000000" + "00000000" + "00000000" |
076 | + "00000000" + "00000000" + "00000000" + "00000000" ; |
077 | return initBitMap; |
078 | } |
079 | |
080 | /** |
081 | * @param args |
082 | */ |
083 | public static void main(String[] args) { |
084 | try { |
085 | //***********************组装8583报文测试--start***********************// |
086 | TreeMap filedMap= new TreeMap(); //报文域 |
087 | filedMap.put( "FIELD003" , "1799" ); //交易码 |
088 | filedMap.put( "FIELD013" , "2013-11-06" ); //交易日期 |
089 | filedMap.put( "FIELD008" , "12345678901" ); //账号 |
090 | filedMap.put( "FIELD033" , "aa索隆bb" ); //注意这个域是变长域! |
091 | filedMap.put( "FIELD036" , "123456" ); //注意这个域是变长域! |
092 | |
093 | byte [] send=make8583(filedMap); |
094 | System.out.println( "完成组装8583报文==" + new String(send,packet_encoding)+ "==" ); |
095 | //***********************组装8583报文测试--end***********************// |
096 | |
097 | |
098 | //***********************解析8583报文测试--start***********************// |
099 | Map back=analyze8583(send); |
100 | System.out.println( "完成解析8583报文==" +back.toString()+ "==" ); |
101 | //***********************解析8583报文测试--end***********************// |
102 | } catch (UnsupportedEncodingException e) { |
103 | e.printStackTrace(); |
104 | } |
105 | |
106 | } |
107 | |
108 | /** |
109 | * 组装8583报文 |
110 | * @param hm |
111 | * @return |
112 | */ |
113 | public static byte [] make8583(TreeMap filedMap){ |
114 | byte [] whoe8583= null ; |
115 | if (filedMap== null ){ |
116 | return null ; |
117 | } |
118 | try { |
119 | String bitMap128=getInitBitMap(); //获取初始化的128位图 |
120 | //按照8583定义器格式化各个域的内容 |
121 | Map all=formatValueTo8583(filedMap,bitMap128); |
122 | // 获取上送报文内容 |
123 | whoe8583=getWhole8583Packet(all); |
124 | return whoe8583; |
125 | } catch (Exception e) { |
126 | e.printStackTrace(); |
127 | } |
128 | return whoe8583; |
129 | } |
130 | /** |
131 | * 获取完整的8583报文体(128域) |
132 | * @param pacBody |
133 | * @return |
134 | */ |
135 | public static byte [] getWhole8583Packet(Map all){ |
136 | if (all== null ||all.get( "formatedFiledMap" )== null ||all.get( "bitMap128" )== null ){ |
137 | return null ; |
138 | } |
139 | try { |
140 | String bitMap128=(String)all.get( "bitMap128" ); |
141 | // 128域位图二进制字符串转16位16进制 |
142 | byte [] bitmaps= get16BitByteFromStr(bitMap128); |
143 | |
144 | TreeMap pacBody=(TreeMap)all.get( "formatedFiledMap" ); |
145 | StringBuffer last128= new StringBuffer(); |
146 | Iterator it=pacBody.keySet().iterator(); |
147 | for (;it.hasNext();){ |
148 | String key=(String)it.next(); |
149 | String value=(String)pacBody.get(key); |
150 | last128.append(value); |
151 | } |
152 | byte [] bitContent = last128.toString().getBytes(packet_encoding); //域值 |
153 | |
154 | //组装 |
155 | byte [] package8583= null ; |
156 | package8583=Lsy8583Util.arrayApend(package8583, bitmaps); |
157 | package8583=Lsy8583Util.arrayApend(package8583, bitContent); |
158 | |
159 | return package8583; |
160 | } catch (Exception e) { |
161 | e.printStackTrace(); |
162 | return null ; |
163 | } |
164 | } |
165 | |
166 | public static Map formatValueTo8583(TreeMap filedMap,String bitMap128){ |
167 | Map all= new HashMap(); |
168 | TreeMap formatedFiledMap= new TreeMap(); //格式化结果 |
169 | if (filedMap!= null ){ |
170 | Iterator it=filedMap.keySet().iterator(); |
171 | for (;it.hasNext();){ |
172 | String fieldName=(String)it.next(); //例如FIELD005 |
173 | String fieldValue=(String)filedMap.get(fieldName); //字段值 |
174 | |
175 | try { |
176 | if (fieldValue == null ) { |
177 | System.out.println( "error:报文域 {" + fieldName + "}为空值" ); |
178 | fieldValue = "" ; |
179 | return null ; |
180 | } |
181 | //将域值编码转换,保证报文编码统一 |
182 | fieldValue= new String(fieldValue.getBytes(packet_encoding),packet_encoding); |
183 | |
184 | // 数据域名称FIELD开头的为128域 |
185 | if (fieldName.startsWith( "FIELD" ) && fieldValue.length() >= 0 ) { |
186 | String fieldNo = fieldName.substring( 5 , 8 ); //例如005 |
187 | // 组二进制位图串 |
188 | bitMap128 = change16bitMapFlag(fieldNo, bitMap128); |
189 | |
190 | // 获取域定义信息 |
191 | String[] fieldDef = Lsy8583Util.map8583Definition.get( "FIELD" + fieldNo).toString().split( "," ); |
192 | String defType=fieldDef[ 0 ]; //类型定义例string |
193 | String defLen=fieldDef[ 1 ]; //长度定义,例20 |
194 | boolean isFixLen= true ; //是否定长判断 |
195 | |
196 | if (defLen.startsWith( "VAR" )){ //变长域 |
197 | isFixLen= false ; |
198 | defLen=defLen.substring( 3 ); //获取VAR2后面的2 |
199 | } |
200 | int fieldLen = fieldValue.getBytes(packet_encoding).length; //字段值得实际长度 |
201 | |
202 | // 判断是否为变长域 |
203 | if (!isFixLen) { // 变长域(变长域最后组装成的效果:例如变长3位,定义var3,这里的3是指长度值占3位,字段值是123456,最后结果就是006123456) |
204 | int defLen1 = Integer.valueOf(defLen); |
205 | if (String.valueOf(fieldLen).length() > ( 10 *defLen1)) { |
206 | System.out.println( "error:字段" + fieldName + "的数据定义长度的长度为" + defLen + "位,长度不能超过" +( 10 *defLen1)); |
207 | return null ; |
208 | } else { |
209 | //将长度值组装入字段 |
210 | fieldValue = getVaryLengthValue(fieldValue, defLen1) + fieldValue; |
211 | } |
212 | } else { //定长域(定长比较好理解,一个字段规定是N位,那么字段值绝对不能超过N位,不足N位就在后面补空格) |
213 | int defLen2 = Integer.valueOf(defLen); |
214 | if (fieldLen > defLen2) { |
215 | System.out.println( "error:字段" + fieldName + "的数据定义长度为" + defLen + "位,长度不能超过" +defLen); |
216 | return null ; |
217 | } else { |
218 | fieldValue=getFixFieldValue(fieldValue,defLen2); //定长处理 |
219 | } |
220 | } |
221 | System.out.println( "组装后报文域 {" + fieldName + "}==" + fieldValue+ "==,域长度:" +fieldValue.getBytes(packet_encoding).length); |
222 | } |
223 | |
224 | // 返回结果赋值 |
225 | if (filedMap.containsKey(fieldName)) { |
226 | if (formatedFiledMap.containsKey(fieldName)) { |
227 | formatedFiledMap.remove(fieldName); |
228 | } |
229 | formatedFiledMap.put(fieldName, fieldValue); |
230 | } else { |
231 | System.out.println( "error:" +fieldName + "配置文件中不存在!" ); |
232 | } |
233 | } catch (Exception e) { |
234 | e.printStackTrace(); |
235 | } |
236 | } //end for |
237 | } |
238 | System.out.println( "" ); |
239 | all.put( "formatedFiledMap" , formatedFiledMap); |
240 | all.put( "bitMap128" , bitMap128); |
241 | return all; |
242 | } |
243 | |
244 | |
245 | |
246 | /** |
247 | * 解析8583报文 |
248 | * |
249 | * @param content8583 |
250 | */ |
251 | public static Map analyze8583( byte [] content8583) { |
252 | TreeMap filedMap= new TreeMap(); |
253 | try { |
254 | // 取位图 |
255 | byte [] bitMap16byte = new byte [ 16 ]; |
256 | System.arraycopy(content8583, 0 , bitMap16byte, 0 , 16 ); |
257 | // 16位图转2进制位图128位字符串 |
258 | String bitMap128Str = get16BitMapStr(bitMap16byte); |
259 | |
260 | //记录当前位置,从位图后开始遍历取值 |
261 | int pos = 16 ; |
262 | // 遍历128位图,取值。注意从FIELD002开始 |
263 | for ( int i = 1 ; i < bitMap128Str.length(); i++) { |
264 | String filedValue = "" ; //字段值 |
265 | String filedName = "FIELD" + getNumThree((i+ 1 )); //FIELD005 |
266 | |
267 | if (bitMap128Str.charAt(i) == '1' ) { |
268 | // 获取域定义信息 |
269 | String[] fieldDef = Lsy8583Util.map8583Definition.get(filedName).toString().split( "," ); |
270 | String defType=fieldDef[ 0 ]; //类型定义例string |
271 | String defLen=fieldDef[ 1 ]; //长度定义,例20 |
272 | boolean isFixLen= true ; //是否定长判断 |
273 | |
274 | if (defLen.startsWith( "VAR" )){ //变长域 |
275 | isFixLen= false ; |
276 | defLen=defLen.substring( 3 ); //获取VAR2后面的2 |
277 | } |
278 | // 截取该域信息 |
279 | if (!isFixLen) { //变长域 |
280 | int defLen1 = Integer.valueOf(defLen); //VAR2后面的2 |
281 | String realLen1= new String(content8583, pos, defLen1, packet_encoding); //报文中实际记录域长,例如16,023 |
282 | int realAllLen=defLen1+Integer.valueOf(realLen1); //该字段总长度(包括长度值占的长度) |
283 | // filedValue = new String(content8583, pos+defLen1, Integer.valueOf(realLen1), packet_encoding); |
284 | byte [] filedValueByte= new byte [Integer.valueOf(realLen1)]; |
285 | System.arraycopy(content8583, pos+defLen1, filedValueByte, 0 , filedValueByte.length); |
286 | filedValue= new String(filedValueByte,packet_encoding); |
287 | pos += realAllLen; //记录当前位置 |
288 | } else { //定长域 |
289 | int defLen2 = Integer.valueOf(defLen); //长度值占的位数 |
290 | filedValue = new String(content8583, pos, defLen2, packet_encoding); |
291 | pos += defLen2; //记录当前位置 |
292 | } |
293 | filedMap.put(filedName, filedValue); |
294 | } |
295 | } //end for |
296 | } catch (Exception e) { |
297 | e.printStackTrace(); |
298 | } |
299 | return filedMap; |
300 | } |
301 | |
302 | //********************************以下是工具方法,有些没有使用到***********************************************************// |
303 | |
304 | /** |
305 | * 复制字符 |
306 | * @param str |
307 | * @param count |
308 | * @return |
309 | */ |
310 | public static String strCopy(String str, int count){ |
311 | StringBuffer sb = new StringBuffer(); |
312 | for ( int i= 0 ;i < count;i++){ |
313 | sb.append(str); |
314 | } |
315 | return sb.toString(); |
316 | } |
317 | /** |
318 | * 将setContent放入set(考虑到数组越界) |
319 | * @param set |
320 | * @param setContent |
321 | * @return |
322 | */ |
323 | public static byte [] setToByte( byte [] set, byte [] setContent){ |
324 | byte [] res= new byte [set.length]; |
325 | if (set== null ||setContent== null ){ |
326 | |
327 | } else { |
328 | if (set.length<setContent.length){ |
329 | |
330 | } else { |
331 | System.arraycopy(setContent, 0 , res, 0 , setContent.length); |
332 | } |
333 | } |
334 | return res; |
335 | } |
336 | public static byte [] setToByte( byte [] set,String setContentStr){ |
337 | byte [] res= new byte [set.length]; |
338 | byte [] setContent; |
339 | try { |
340 | setContent = setContentStr.getBytes(packet_encoding); |
341 | res=setToByte(res,setContent); |
342 | } catch (UnsupportedEncodingException e) { |
343 | e.printStackTrace(); |
344 | } |
345 | return res; |
346 | } |
347 | |
348 | public static String getPacketLen( int len){ |
349 | String res= "" ; |
350 | String lenStr=String.valueOf(len); |
351 | int lenC= 4 -lenStr.length(); |
352 | res=strCopy( "0" ,lenC)+lenStr; |
353 | return res; |
354 | } |
355 | public static String getPacketLen(String lenStr){ |
356 | String res= "" ; |
357 | if (lenStr== null ){ |
358 | |
359 | } else { |
360 | res=getPacketLen(Integer.valueOf(lenStr)); |
361 | } |
362 | return res; |
363 | } |
364 | |
365 | |
366 | /** |
367 | * 返回a和b的组合,实现累加功能 |
368 | * @param a |
369 | * @param b |
370 | * @return |
371 | */ |
372 | public static byte [] arrayApend( byte [] a, byte [] b){ |
373 | int a_len=(a== null ? 0 :a.length); |
374 | int b_len=(b== null ? 0 :b.length); |
375 | byte [] c= new byte [a_len+b_len]; |
376 | if (a_len== 0 &&b_len== 0 ){ |
377 | return null ; |
378 | } else if (a_len== 0 ){ |
379 | System.arraycopy(b, 0 , c, 0 , b.length); |
380 | } else if (b_len== 0 ){ |
381 | System.arraycopy(a, 0 , c, 0 , a.length); |
382 | } else { |
383 | System.arraycopy(a, 0 , c, 0 , a.length); |
384 | System.arraycopy(b, 0 , c, a.length, b.length); |
385 | } |
386 | return c; |
387 | } |
388 | |
389 | |
390 | /** |
391 | * 改变128位图中的标志为1 |
392 | * @param fieldNo |
393 | * @param res |
394 | * @return |
395 | */ |
396 | public static String change16bitMapFlag(String fieldNo, String res) { |
397 | int indexNo=Integer.parseInt(fieldNo); |
398 | res = res.substring( 0 , indexNo- 1 ) + "1" + res.substring(indexNo); |
399 | return res; |
400 | } |
401 | |
402 | |
403 | /** |
404 | * 位图操作 |
405 | * |
406 | * 把16位图的字节数组转化成128位01字符串 |
407 | * @param packet_header_map |
408 | * @return |
409 | */ |
410 | public static String get16BitMapStr( byte [] bitMap16){ |
411 | String bitMap128 = "" ; |
412 | // 16位图转2进制位图128位字符串 |
413 | for ( int i = 0 ; i < bitMap16.length; i++) { |
414 | int bc = bitMap16[i]; |
415 | bc=(bc< 0 )?(bc+ 256 ):bc; |
416 | String bitnaryStr=Integer.toBinaryString(bc); //二进制字符串 |
417 | // 左补零,保证是8位 |
418 | String rightBitnaryStr = strCopy( "0" ,Math.abs( 8 -bitnaryStr.length())) + bitnaryStr; //位图二进制字符串 |
419 | // 先去除多余的零,然后组装128域二进制字符串 |
420 | bitMap128+=rightBitnaryStr; |
421 | } |
422 | return bitMap128; |
423 | } |
424 | |
425 | /** |
426 | * 位图操作 |
427 | * |
428 | * 把128位01字符串转化成16位图的字节数组 |
429 | * @param packet_header_map |
430 | * @return |
431 | */ |
432 | public static byte [] get16BitByteFromStr(String str_128){ |
433 | byte [] bit16= new byte [ 16 ]; |
434 | try { |
435 | if (str_128== null ||str_128.length()!= 128 ){ |
436 | return null ; |
437 | } |
438 | // 128域位图二进制字符串转16位16进制 |
439 | byte [] tmp=str_128.getBytes(packet_encoding); |
440 | int weight; //权重 |
441 | byte [] strout = new byte [ 128 ]; |
442 | int i, j, w = 0 ; |
443 | for (i = 0 ; i < 16 ; i++) { |
444 | weight = 0x0080 ; |
445 | for (j = 0 ; j < 8 ; j++) { |
446 | strout[i] += ((tmp[w]) - '0' ) * weight; |
447 | weight /= 2 ; |
448 | w++; |
449 | } |
450 | bit16[i] = strout[i]; |
451 | } |
452 | } catch (UnsupportedEncodingException e) { |
453 | e.printStackTrace(); |
454 | } |
455 | return bit16; |
456 | } |
457 | |
458 | |
459 | /** |
460 | * 从完整的8583报文中获取位图(16字节数组) |
461 | * @param packet |
462 | * @return |
463 | */ |
464 | public static byte [] getPacketHeaderMap( byte [] packet){ |
465 | byte [] packet_header_map = new byte [ 16 ]; |
466 | if (packet== null ||packet.length< 16 ){ |
467 | return null ; |
468 | } |
469 | for ( int i= 0 ;i< 16 ;i++){ |
470 | packet_header_map[i]=packet[i]; |
471 | } |
472 | return packet_header_map; |
473 | } |
474 | /** |
475 | * 从完整的8583报文中获取16位图,转化成128位的01字符串 |
476 | * |
477 | * @param content8583 |
478 | * @return |
479 | */ |
480 | public static String get16BitMapFrom8583Byte( byte [] content8583){ |
481 | // 取位图 |
482 | byte [] bitMap16 = getPacketHeaderMap(content8583); |
483 | // 16位图转2进制位图128位字符串 |
484 | String bitMap128 = get16BitMapStr(bitMap16); |
485 | |
486 | return bitMap128; |
487 | } |
488 | |
489 | |
490 | |
491 | //返回字段号码,例如005 |
492 | public static String getNumThree( int i){ |
493 | String len= "" ; |
494 | String iStr=String.valueOf(i); |
495 | len=strCopy( "0" , 3 -iStr.length())+iStr; |
496 | return len; |
497 | } |
498 | |
499 | /** |
500 | * 获取字符串变长值 |
501 | * @param valueStr |
502 | * @param defLen |
503 | * 例如getFixLengthValue("12345678", 2)返回08 |
504 | * 例如getFixLengthValue("12345678", 3)返回008 |
505 | * |
506 | * 注意变长长度的计算: |
507 | * 长度的判断使用转化后的字节数组长度,因为中文在不同的编码方式下,长度是不同的,GBK是2,UTF-8是3,按字符创长度算就是1. |
508 | * 解析报文是按照字节来解析的,所以长度以字节长度为准,防止中文带来乱码。 |
509 | * |
510 | * 比如一个变长域:aa索隆bb,如果按照字符串计算长度那么就是6,最后是06aa索隆bb。 |
511 | * 这样在解析时按照字节解析长度就乱了,因为按照GBK字节解析,一个汉字占2,按照UTF-8解析,一个汉字占3. |
512 | * 所以在计算时必须按照字节长度为准!按照我们设置的UTF-8编码结果就是10aa索隆bb. |
513 | * 这样在解析时长度正好是10,也就不会乱了。 |
514 | * @return |
515 | */ |
516 | public static String getVaryLengthValue(String valueStr, int defLen){ |
517 | return getVaryLengthValue(valueStr,defLen,packet_encoding); |
518 | } |
519 | public static String getVaryLengthValue(String valueStr, int defLen,String encoding){ |
520 | String fixLen= "" ; |
521 | try { |
522 | if (valueStr== null ){ |
523 | return strCopy( "0" ,defLen); |
524 | } else { |
525 | byte [] valueStrByte= null ; |
526 | //这里最好指定编码,不使用平台默认编码 |
527 | if (encoding== null ||encoding.trim().equals( "" )){ |
528 | valueStrByte=valueStr.getBytes(); |
529 | } else { |
530 | valueStrByte=valueStr.getBytes(encoding); |
531 | } |
532 | //长度的判断使用转化后的字节数组长度,因为中文在不同的编码方式下,长度是不同的,GBK是2,UTF-8是3,按字符创长度算就是1. |
533 | //解析报文是按照字节来解析的,所以长度以字节长度为准,防止中文带来乱码 |
534 | if (valueStrByte.length>( 10 *defLen)){ |
535 | return null ; |
536 | } else { |
537 | int len=valueStrByte.length; //字段实际长度 |
538 | String len1=String.valueOf(len); |
539 | fixLen=strCopy( "0" ,(defLen-len1.length()))+len1; |
540 | } |
541 | } |
542 | } catch (UnsupportedEncodingException e) { |
543 | e.printStackTrace(); |
544 | } |
545 | return fixLen; |
546 | } |
547 | |
548 | /** |
549 | * 将字段值做定长处理,不足定长则在后面补空格 |
550 | * @param valueStr |
551 | * @param defLen |
552 | * @return |
553 | */ |
554 | public static String getFixFieldValue(String valueStr, int defLen){ |
555 | return getFixFieldValue(valueStr,defLen,packet_encoding); |
556 | } |
557 | public static String getFixFieldValue(String valueStr, int defLen,String encoding){ |
558 | String fixLen= "" ; |
559 | try { |
560 | if (valueStr== null ){ |
561 | return strCopy( " " ,defLen); |
562 | } else { |
563 | byte [] valueStrByte= null ; |
564 | //这里最好指定编码,不使用平台默认编码 |
565 | if (encoding== null ||encoding.trim().equals( "" )){ |
566 | valueStrByte=valueStr.getBytes(); |
567 | } else { |
568 | valueStrByte=valueStr.getBytes(encoding); |
569 | } |
570 | //长度的判断使用转化后的字节数组长度,因为中文在不同的编码方式下,长度是不同的,GBK是2,UTF-8是3,按字符创长度算就是1. |
571 | //解析报文是按照字节来解析的,所以长度以字节长度为准,防止中文带来乱码 |
572 | if (valueStrByte.length>defLen){ |
573 | return null ; |
574 | } else { |
575 | fixLen=valueStr+strCopy( " " ,defLen-valueStrByte.length); |
576 | } |
577 | } |
578 | } catch (UnsupportedEncodingException e) { |
579 | e.printStackTrace(); |
580 | } |
581 | |
582 | return fixLen; |
583 | } |
584 | |
585 | |
586 | public static String getPacket_encoding() { |
587 | return packet_encoding; |
588 | } |
589 | |
590 | public static void setPacket_encoding(String packet_encoding) { |
591 | Lsy8583Util.packet_encoding = packet_encoding; |
592 | } |
593 | |
594 | public static Map getMap8583Definition() { |
595 | return map8583Definition; |
596 | } |
597 | |
598 | public static void setMap8583Definition(Map map8583Definition) { |
599 | Lsy8583Util.map8583Definition = map8583Definition; |
600 | } |
601 | |
602 | } |
报文域配置文件:config_8583.properties
001 | FIELD002 = string,16 |
002 | FIELD003 = string,4 |
003 | FIELD004 = string,20 |
004 | FIELD005 = string,20 |
005 | FIELD006 = string,20 |
006 | FIELD007 = string,10 |
007 | FIELD008 = string,32 |
008 | FIELD009 = string,3 |
009 | FIELD010 = string,20 |
010 | FIELD011 = string,6 |
011 | FIELD012 = string,6 |
012 | FIELD013 = string,10 |
013 | FIELD014 = string,10 |
014 | FIELD015 = string,10 |
015 | FIELD016 = string,6 |
016 | FIELD017 = string,6 |
017 | FIELD018 = string,6 |
018 | FIELD019 = string,6 |
019 | FIELD020 = string,7 |
020 | FIELD021 = string,7 |
021 | FIELD022 = string,3 |
022 | FIELD023 = string,3 |
023 | FIELD024 = string,8 |
024 | FIELD025 = string,5 |
025 | FIELD026 = string,8 |
026 | FIELD027 = string,1 |
027 | FIELD028 = string,5 |
028 | FIELD029 = string,5 |
029 | FIELD030 = string,5 |
030 | FIELD031 = string,10 |
031 | FIELD032 = string,VAR2 |
032 | FIELD033 = string,VAR2 |
033 | FIELD034 = string,VAR2 |
034 | FIELD035 = string,VAR2 |
035 | FIELD036 = string,VAR3 |
036 | FIELD037 = string,10 |
037 | FIELD038 = string,4 |
038 | FIELD039 = string,6 |
039 | FIELD040 = string,2 |
040 | FIELD041 = string,3 |
041 | FIELD042 = string,16 |
042 | FIELD043 = string,20 |
043 | FIELD044 = string,VAR2 |
044 | FIELD045 = string,VAR2 |
045 | FIELD046 = string,VAR3 |
046 | FIELD047 = string,VAR3 |
047 | FIELD048 = string,VAR3 |
048 | FIELD049 = string,3 |
049 | FIELD050 = string,VAR3 |
050 | FIELD051 = string,VAR3 |
051 | FIELD052 = string,16 |
052 | FIELD053 = string,VAR2 |
053 | FIELD054 = string,VAR3 |
054 | FIELD055 = string,VAR3 |
055 | FIELD056 = string,VAR3 |
056 | FIELD057 = string,VAR3 |
057 | FIELD058 = string,VAR3 |
058 | FIELD059 = string,VAR3 |
059 | FIELD060 = string,VAR3 |
060 | FIELD061 = string,VAR3 |
061 | FIELD062 = string,VAR3 |
062 | FIELD063 = string,VAR3 |
063 | FIELD064 = string,16 |
064 | FIELD065 = string,2 |
065 | FIELD066 = string,1 |
066 | FIELD067 = string,2 |
067 | FIELD068 = string,16 |
068 | FIELD069 = string,16 |
069 | FIELD070 = string,3 |
070 | FIELD071 = string,4 |
071 | FIELD072 = string,2 |
072 | FIELD073 = string,10 |
073 | FIELD074 = string,10 |
074 | FIELD075 = string,22 |
075 | FIELD076 = string,17 |
076 | FIELD077 = string,32 |
077 | FIELD078 = string,VAR3 |
078 | FIELD079 = string,6 |
079 | FIELD080 = string,32 |
080 | FIELD081 = string,32 |
081 | FIELD082 = string,4 |
082 | FIELD083 = string,4 |
083 | FIELD084 = string,6 |
084 | FIELD085 = string,15 |
085 | FIELD086 = string,20 |
086 | FIELD087 = string,20 |
087 | FIELD088 = string,20 |
088 | FIELD089 = string,6 |
089 | FIELD090 = string,9 |
090 | FIELD091 = string,9 |
091 | FIELD092 = string,9 |
092 | FIELD093 = string,VAR3 |
093 | FIELD094 = string,2 |
094 | FIELD095 = string,42 |
095 | FIELD096 = string,8 |
096 | FIELD097 = string,42 |
097 | FIELD098 = string,3 |
098 | FIELD099 = string,3 |
099 | FIELD100 = string,80 |
100 | FIELD101 = string,VAR3 |
101 | FIELD102 = string,80 |
102 | FIELD103 = string,80 |
103 | FIELD104 = string,VAR3 |
104 | FIELD105 = string,VAR3 |
105 | FIELD106 = string,VAR3 |
106 | FIELD107 = string,VAR3 |
107 | FIELD108 = string,2 |
108 | FIELD109 = string,VAR3 |
109 | FIELD110 = string,9 |
110 | FIELD111 = string,VAR3 |
111 | FIELD112 = string,VAR3 |
112 | FIELD113 = string,VAR3 |
113 | FIELD114 = string,VAR3 |
114 | FIELD115 = string,3 |
115 | FIELD116 = string,VAR3 |
116 | FIELD117 = string,VAR3 |
117 | FIELD118 = string,VAR3 |
118 | FIELD119 = string,VAR3 |
119 | FIELD120 = string,VAR3 |
120 | FIELD121 = string,32 |
121 | FIELD122 = string,VAR3 |
122 | FIELD123 = string,VAR3 |
123 | FIELD124 = string,VAR3 |
124 | FIELD125 = string,VAR3 |
125 | FIELD126 = string,VAR3 |
126 | FIELD127 = string,VAR3 |
127 | FIELD128 = string,8 |
简单说下,
FIELD031 = string,10
FIELD032 = string,VAR2
string代表域值类型(我只用到了string,别的就没定义了),10表示该域是定长10位。
如果是变长就定义成var,后面的2表示变长长度占2位,那么域最大就是99位。
运行打印结果:
1 | /D:/AppleZero/workSpace/apple/target/classes/ |
2 | Lsy8583Util使用编码配置:[encoding:UTF-8] |
3 | 组装后报文域 {FIELD003}==1799==,域长度:4 |
4 | 组装后报文域 {FIELD008}==12345678901 ==,域长度:32 |
5 | 组装后报文域 {FIELD013}==2013-11-06==,域长度:10 |
6 | 组装后报文域 {FIELD033}==10aa索隆bb==,域长度:12 |
7 | 组装后报文域 {FIELD036}==006123456==,域长度:9 |
8 | |
9 | 完成组装8583报文==? |
打印的有些字节复制出来就看不到了,我把控制台打印截图吧。