在iOS开发中,我们常常需要对十六进制、二进制字符串、NSData、整数、字节序等数据类型进行转换与处理,尤其在与硬件通信(如蓝牙BLE、WIFI)、网络协议、加密等场景中使用频繁。
本文将介绍一个我在iOS开发过程中通用且实用的 Objective-C 工具类 ------ ParseDataTool
,它封装了常见的数据转换逻辑,并提供了清晰的 API 接口,方便项目中直接使用。
工具类简介
该工具类主要功能如下:
- 十六进制字符串与 NSData、整数之间的互相转换
- 大端、小端字节序处理
- 十六进制字符串格式化显示(方便打印调试)
- 异或计算校验
- NSData 安全裁剪,防止越界崩溃
- 字节反转(适用于小端传输转大端展示)
工具类接口头文件(ParseDataTool.h)
js
//
// ParseDataTool.h
// 数据转换工具类
//
// Created by tangbin on 2025/01/03.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/// 数据转换工具类
@interface ParseDataTool : NSObject
/// 小端NSData转整数
+ (NSInteger)transLittleEndianDataToInteger:(NSData *)data;
/// 大端NSData转整数
+ (NSInteger)convertDataToInteger:(NSData *)data;
/// NSData 转十六进制字符串
+ (NSString *)transDataToHexString:(NSData *)data;
/// 十六进制字符串转 NSData
+ (NSData *)transToDataWithString:(NSString *)hexString;
/// 十六进制字符串倒序排列
+ (NSString *)invertedOrderWithStr:(NSString *)str;
/// 十六进制字符串转十进制整数
+ (NSInteger)convertToDecimalFromHex:(NSString *)hexString;
/// 格式化为 "aa bb cc dd"
+ (NSString *)describeBlankFormatWithString:(NSString *)dataString;
/// 格式化为 "0xaa, 0xbb, 0xcc, 0xdd"
+ (NSString *)describeBytesFormatWithString:(NSString *)dataString;
/// 字节序转换:小端 <-> 大端
+ (NSData *)convertNSData:(NSData *)source;
/// 将字符串按大端字节序排列(默认倒序)
+ (NSString *)transString2BigMode:(NSString *)string;
/// 字节异或校验值(返回字符串)
+ (NSString *)xorWithDataString:(NSString *)dataString;
/// 比较 NSData 异或校验结果是否为某个值
+ (BOOL)compareImageData:(NSData *)imageData withXORValue:(NSInteger)xorValue;
/// 安全截取NSData(越界不会崩溃)
+ (NSData *)subMyData:(NSData *)data range:(NSRange)range;
/// 长度交换:16位数(用于字节反转)
+ (UInt16)numswap:(int)len;
@end
NS_ASSUME_NONNULL_END
工具类实现文件(ParseDataTool.m)
js
//
// ParseDataTool.m
// 数据转换工具类
//
// Created by tangbin on 2025/01/03.
//
#import "ParseDataTool.h"
@implementation ParseDataTool
#pragma mark - 十六进制与整数转换
+ (NSInteger)transLittleEndianDataToInteger:(NSData *)data {
if (!data || data.length == 0) return 0;
UInt32 value = 0;
[data getBytes:&value length:MIN(sizeof(value), data.length)];
return CFSwapInt32LittleToHost(value);
}
+ (NSInteger)convertDataToInteger:(NSData *)data {
if (!data || data.length == 0) return 0;
UInt32 value = 0;
[data getBytes:&value length:MIN(sizeof(value), data.length)];
return CFSwapInt32BigToHost(value);
}
#pragma mark - 十六进制与字符串转换
+ (NSString *)transDataToHexString:(NSData *)data {
if (!data || data.length == 0) return @"";
const unsigned char *dataBuffer = data.bytes;
NSMutableString *hexString = [NSMutableString stringWithCapacity:data.length * 2];
for (int i = 0; i < data.length; ++i) {
[hexString appendFormat:@"%02x", dataBuffer[i]];
}
return [hexString copy];
}
+ (NSData *)transToDataWithString:(NSString *)hexString {
if (!hexString || hexString.length == 0) return [NSData data];
NSMutableData *data = [NSMutableData data];
NSString *cleanString = [hexString stringByReplacingOccurrencesOfString:@" " withString:@""];
for (NSInteger i = 0; i < cleanString.length; i += 2) {
NSString *byteString = [cleanString substringWithRange:NSMakeRange(i, 2)];
unsigned int byteValue = 0;
[[NSScanner scannerWithString:byteString] scanHexInt:&byteValue];
UInt8 byte = (UInt8)byteValue;
[data appendBytes:&byte length:1];
}
return [data copy];
}
+ (NSString *)invertedOrderWithStr:(NSString *)str {
if (!str || str.length % 2 != 0) return @"";
NSMutableString *result = [NSMutableString string];
for (NSInteger i = str.length; i > 0; i -= 2) {
NSString *byte = [str substringWithRange:NSMakeRange(i - 2, 2)];
[result appendString:byte];
}
return [result copy];
}
+ (NSInteger)convertToDecimalFromHex:(NSString *)hexString {
if (!hexString || hexString.length == 0) return 0;
unsigned int result = 0;
[[NSScanner scannerWithString:hexString] scanHexInt:&result];
return result;
}
#pragma mark - 格式化输出辅助
+ (NSString *)describeBlankFormatWithString:(NSString *)dataString {
if (!dataString || dataString.length == 0) return @"";
NSMutableArray *components = [NSMutableArray array];
for (NSInteger i = 0; i < dataString.length; i += 2) {
if (i + 2 <= dataString.length) {
NSString *byte = [dataString substringWithRange:NSMakeRange(i, 2)];
[components addObject:byte];
}
}
return [components componentsJoinedByString:@" "];
}
+ (NSString *)describeBytesFormatWithString:(NSString *)dataString {
if (!dataString || dataString.length == 0) return @"";
NSMutableArray *components = [NSMutableArray array];
for (NSInteger i = 0; i < dataString.length; i += 2) {
if (i + 2 <= dataString.length) {
NSString *byte = [dataString substringWithRange:NSMakeRange(i, 2)];
[components addObject:[NSString stringWithFormat:@"0x%@", byte]];
}
}
return [components componentsJoinedByString:@", "];
}
#pragma mark - 大小端与字符串处理
+ (NSString *)transString2BigMode:(NSString *)string {
// 默认假设为小端,按两位进行倒序
return [self invertedOrderWithStr:string];
}
+ (NSData *)convertNSData:(NSData *)source {
if (!source || source.length == 0) return [NSData data];
NSMutableData *result = [NSMutableData dataWithCapacity:source.length];
const Byte *srcBytes = source.bytes;
for (NSInteger i = source.length - 1; i >= 0; i--) {
[result appendBytes:&srcBytes[i] length:1];
}
return [result copy];
}
+ (UInt16)numswap:(int)len {
UInt16 value = (UInt16)len;
return (value >> 8) | (value << 8);
}
#pragma mark - 异或计算与校验
+ (NSString *)xorWithDataString:(NSString *)dataString {
if (!dataString || dataString.length % 2 != 0) return @"00";
UInt8 xorResult = 0x00;
for (NSInteger i = 0; i < dataString.length; i += 2) {
NSString *byteStr = [dataString substringWithRange:NSMakeRange(i, 2)];
unsigned int byte = 0;
[[NSScanner scannerWithString:byteStr] scanHexInt:&byte];
xorResult ^= (UInt8)byte;
}
return [NSString stringWithFormat:@"%02x", xorResult];
}
+ (BOOL)compareImageData:(NSData *)imageData withXORValue:(NSInteger)xorValue {
if (!imageData || imageData.length == 0) return NO;
UInt8 result = 0x00;
const Byte *bytes = imageData.bytes;
for (NSInteger i = 0; i < imageData.length; i++) {
result ^= bytes[i];
}
return result == xorValue;
}
#pragma mark - 安全的数据裁剪
+ (NSData *)subMyData:(NSData *)data range:(NSRange)range {
if (!data || data.length == 0) return [NSData data];
if (range.location + range.length > data.length) return [NSData data];
return [data subdataWithRange:range];
}
@end
工具类适用场景
- BLE蓝牙设备通信(特征值读写、帧协议解析)
- 自定义数据加密与解密
- 十六进制计算与打印调试
- 文件与图片二进制数据分析
- 网络数据传输中的底层数据封装/解析
代码延伸
- 大小端模式:iOS 是基于大端的架构,但许多硬件设备采用小端,处理时需注意。
- NSData 安全性 :不使用越界的
subdataWithRange:
,避免运行时崩溃。 - 异或校验:常用于通信协议中的数据完整性校验,快速但不适合高安全场景。
最后
在实际开发中非常实用的 Objective-C 工具类 ParseDataTool
,它封装了常见的二进制数据处理方法,可直接用于 iOS 项目开发,也适合作为学习字节、编码、异或等底层知识的参考工具类。如有写错的地方欢迎各位不吝赐教,谢谢大家。