OC封装的TLV数据格式解析库

原创 2013年12月02日 18:54:49

作者:朱克锋

邮箱:zhukefeng@iboxpay.com

转载请注明出处:http://blog.csdn.net/linux_zkf



TLV是一种可变格式,意思就是:

Type类型, Lenght长度,Value值;

Type和Length的长度固定,一般那是2、4个字节(这里统一采用4个字节);

Value的长度有Length指定;

解码方法:

1.      读取type 用ntohl转换为主机字节序得到类型,指针偏移+4

2.      读取lengh用ntohl转换为主机字节序得到长度;指针偏移+4

3.      根据得到的长度读取value,若value数据类型为int、char、short,用ntohl转换为主机字节序,指针偏移+4;若value数据类型为字符串类型,指针偏移+length

类型(Type)字段是关于标签和编码格式的信息;

长度 (Length)字段定义数值的长度;

内容(Value)字段表示实际的数值。

因此,一个编码值又称TLV(Type,Length,Value)三元组。编码可以是基本型或结构型,如果它表示一个简单类型的、完整的显式值,那么编码就是基本型 (primitive);如果它表示的值具有嵌套结构,那么编码就是结构型(constructed)。

以上是对tlv的简单解释,从网上搜集的资源来看,用C、C++来写的开源软件都非常的复杂,我这里使用了很少的OC代码实现了一个简单实用的TLV解析库,供各位参考使用


TLV数据结构

//

//  TLV.h

//  CashBox

//

//  Created by ZKF on 13-11-18.

//  Copyright (c) 2013 ZKF. All rights reserved.

//


#import <Foundation/Foundation.h>


@interface TLV : NSObject


@property (nonatomic, assign) NSInteger length;

@property (nonatomic, retain) NSString *value;

@property (nonatomic, retain) NSString *tag;


@end

//

//  TLV.m

//  CashBox

//

//  Created by ZKF on 13-11-18.

//  Copyright (c) 2013 ZKF. All rights reserved.

//


#import "TLV.h"


@implementation TLV

@synthesize tag;

@synthesize value;

@synthesize length;

@end



解析数据结构

//

//  LPositon.h

//  CashBox

//

//  Created by ZKF on 13-11-18.

//  Copyright (c) 2013 ZKF. All rights reserved.

//


#import <Foundation/Foundation.h>


@interface LPositon : NSObject

@property (nonatomic,assign) NSInteger vl;

@property (nonatomic,assign) NSInteger position;

@end

//

//  LPositon.m

//  CashBox

//

//  Created by ZKF on 13-11-18.

//  Copyright (c) 2013 ZKF. All rights reserved.

//


#import "LPositon.h"


@implementation LPositon

@synthesize vl;

@synthesize position;

@end



解析代码

//

//  SAXUnionFiled55Utils.h

//  CashBox

//

//  Created by ZKF on 13-11-18.

//  Copyright (c) 2013 ZKF. All rights reserved.

//


#import <Foundation/Foundation.h>

#import "TLV.h"

#import "LPositon.h"

@interface TLVParseUtils : NSObject

-(NSArray*) saxUnionField55_2List:(NSString*) hexfiled55;

@end

//

//  SAXUnionFiled55Utils.m

//  CashBox

//

//  Created by ZKF on 13-11-18.

//  Copyright (c) 2013 ZKF. All rights reserved.

//


#import "TLVParseUtils.h"


@implementation TLVParseUtils


/**

 * 银联55

 *

 * 本域将根据不同的交易种类包含不同的子域。银联处理中心仅在受理方和发卡方之间传递这些适用于IC卡交易的特有数据,而不对它们进行任何修改和处理。

 * 为适应该子域需要不断变化的情况

 * ,本域采用TLVtag-length-value)的表示方式,即每个子域由tag标签(T),子域取值的长度(L)和子域取值(V)构成。

 * tag标签的属性为bit

 * ,由16进制表示,占12个字节长度。例如,"9F33"为一个占用两个字节的tag标签。而"95"为一个占用一个字节的tag标签

 * 。若tag标签的第一个字节

 * (注:字节排序方向为从左往右数,第一个字节即为最左边的字节。bit排序规则同理。)的后五个bit"11111",则说明该tag占两个字节

 * ,例如"9F33";否则占一个字节,例如"95" 子域长度(即L本身)的属性也为bit,占13个字节长度。具体编码规则如下: a)

 * L字段最左边字节的最左bit位(即bit8)为0,表示该L字段占一个字节,它的后续7bit位(即bit7bit1)表示子域取值的长度,

 * 采用二进制数表示子域取值长度的十进制数

 * 。例如,某个域取值占3个字节,那么其子域取值长度表示为"00000011"。所以,若子域取值的长度在1127

 * 字节之间,那么该L字段本身仅占一个字节。 b)

 * L字段最左边字节的最左bit位(即bit8)为1,表示该L字段不止占一个字节,那么它到底占几个字节由该最左字节的后续7bit

 * (即bit7bit1)的十进制取值表示。例如,若最左字节为10000010,表示L字段除该字节外,后面还有两个字节。其后续字节

 * 的十进制取值表示子域取值的长度。例如,若L字段为"1000 0001 1111 1111",表示该子域取值占255个字节。

 * 所以,若子域取值的长度在128255字节之间,那么该L字段本身需占两个字节

 *

 * @return tlv NSArray

 */

-(NSArray*) saxUnionField55_2List:(NSString*) hexfiled55

{

    

    if (nil == hexfiled55) {

        

    }

    return [[[self builderTLV:hexfiled55] retain] autorelease];

}


-(NSArray*) builderTLV:(NSString *)hexString

{

    NSMutableArray *arr = [[[NSMutableArray alloc] initWithCapacity:10] autorelease];

    int position = 0;

    while (position != hexString.length) {

        NSString * _hexTag = [self getUnionTag:hexString P:position];

        NSLog(@"hex tag :%@",_hexTag);

        if ([_hexTag isEqualToString:@"00"] || [_hexTag isEqualToString:@"0000"]) {

            position += _hexTag.length;

            continue;

        }

        position += _hexTag.length;

        LPositon *l_position = [[[self getUnionLAndPosition:hexString P:position] retain] autorelease];;

        int _vl = l_position.vl;

        NSLog(@"value len :%i",_vl);

        position = l_position.position;

        

        NSString* _value = [hexString substringWithRange:NSMakeRange(position, _vl * 2)];

        NSLog(@"value :%@",_value);

      

        position = position + _value.length;

        TLV *tlv = [[[TLV alloc] init] autorelease];

        tlv.tag = _hexTag;

        tlv.value = _value;

        tlv.length = _vl;

        [arr addObject:tlv];

    }

    return arr;

}


int ChangeNum(char * str,int length)

{

    char  revstr[128] = {0};  //根据十六进制字符串的长度,这里注意数组不要越界

    int   num[16] = {0};

    int   count = 1;

    int   result = 0;

    strcpy(revstr,str);

    for (int i = length - 1;i >= 0;i--)

    {

        if ((revstr[i] >= '0') && (revstr[i] <= '9')) {

            num[i] = revstr[i] - 48;//字符0ASCII值为48

        } else if ((revstr[i] >= 'a') && (revstr[i] <= 'f')) {

            num[i] = revstr[i] - 'a' + 10;

        } else if ((revstr[i] >= 'A') && (revstr[i] <= 'F')) {

            num[i] = revstr[i] - 'A' + 10;

        } else {

            num[i] = 0;

        }

        result = result+num[i]*count;

        count = count*16;//十六进制(如果是八进制就在这里乘以8)

    }

    return result;

}


-(LPositon *)getUnionLAndPosition:(NSString *)hexString P:(NSInteger) position

{

    NSString *firstByteString = [hexString substringWithRange:NSMakeRange(position, 2)];

    int i = ChangeNum((char *)[firstByteString UTF8String],2);

    

    NSString * hexLength = @"";

    if (((i >> 7) & 1) == 0) {

        hexLength = [hexString substringWithRange:NSMakeRange(position, 2)];

        position = position + 2;

        

    } else {

        // 当最左侧的bit位为1的时候,取得后7bit的值,

        int _L_Len = i & 127;

        position = position + 2;

        hexLength = [hexString substringWithRange:NSMakeRange(position, _L_Len * 2)];

        // position表示第一个字节,后面的表示有多少个字节来表示后面的Value

        position = position + _L_Len * 2;

        

    }

    LPositon *LP = [[[LPositon alloc] init] autorelease];

    LP.vl = ChangeNum((char *)[hexLength UTF8String],2);

    LP.position = position;

    return LP;

}


-(NSString*) getUnionTag:(NSString* )hexString P:(NSInteger) position

{

    NSString* firstByte = [hexString substringWithRange:NSMakeRange(position, 2)];

    int i = ChangeNum((char *)[firstByte UTF8String],2);

    if ((i & 0x1f) == 0x1f) {

        return [hexString substringWithRange:NSMakeRange(position, 4)];

    } else {

        return [hexString substringWithRange:NSMakeRange(position, 2)];

    }

}

@end

测试代码

- (void)viewDidLoad

{

    [super viewDidLoad];

// Do any additional setup after loading the view, typically from a nib.

    TLVParseUtils*s = [[[TLVParseUtils alloc] init] autorelease];

    NSArray *tlvArr =  [s saxUnionField55_2List:@"9F260879CC8EC5A09FB9479F2701809F100807010199A0B806019F3704000000009F360201C2950500001800009A031205089C01609F02060000000000005F2A02015682027D009F1A0201569F03060000000000009F3303E0F0F09F34036003029F3501119F1E0832303033313233318405FFFFFFFFFF9F090220069F4104000000019F74064543433030319F631030313032303030308030303030303030"];

    

    NSLog(@"tlv arr :%@",tlvArr);

}


获取源代码请到https://github.com/zhukefeng-ios/TVLParse







版权声明:本文为博主原创文章,欢迎转载。转载请注明出处http://blog.csdn.net/linux_zkf,朱克锋--大话商学院系列

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

ISO8583报文工具类

ISO8583报文工具类(组装和解析报文)      很久没来csdn了。现在的工作地点在银行,妈的,不让上网啊。 写写博客其实是对自己知识的总结,这么长时间了,也该写点东西了。接触银行的项目,避...
  • down177
  • down177
  • 2015年06月03日 10:05
  • 916

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

TLV 解析(Java)

TLV数据解析的函数整理(Java ) 如有问题,请拍板砖!!会及时更正!! 废话不多说直接上代码!!!...
  • grain11
  • grain11
  • 2017年05月25日 19:45
  • 709

金融系统中PBOC/EMV的TLV的算法实现(含C++/C#)

     TLV即Tag-Length-Value,常在IC卡与POS终端设备中通过这样的一个应用通信协议进行数据交换。在金融系统以及认证中,PBOC以及EMV的认证规范文档上面也有对TLV做了...

NFC的读写卡模式——前台调度系统

接着上一篇文章来说,在前一个文章中,我们为大家简单介绍了一下什么是NFC,在这节内容中,我们为大家介绍一下NFC的读写卡模式的开发。 读写卡模式是通过手机对nfc标签卡信息经行读写操...

[转]android点滴之NFC手机如何轻松读取银行卡信息?

 自支付宝钱包8.0推出了NFC新功能,只要将支持NFC功能的手机靠近公交卡、银行卡等带有芯片的IC卡上,可迅速读取卡内余额、卡的信息,还可以给卡进行充值,非常贴心实用。 ...

java解析TLV格式数据

TLV:TLV格式数据是指由Tag,Length,Value组成的数据。具体说明如下:            tag标签的属性为bit,由16进制表示,占1~2个字节长度。例如,“9F3...

java解析TLV格式数据

TLV:TLV格式数据是指由Tag,Length,Value组成的数据。具体说明如下:            tag标签的属性为bit,由16进制表示,占1~2个字节长度。例如,“9F33”为一个占用...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:OC封装的TLV数据格式解析库
举报原因:
原因补充:

(最多只允许输入30个字)