ios - 从 NSData : NSData Parsing 中查找不同的组件

标签 ios parsing nsdata

我的 NSData 格式为“Hello$World$Image”($ 用作分隔符来区分不同的部分数据)我使用以下代码制作的

NSData *data=[@"$" dataUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@",data);
NSData *data2=[@"Hello" dataUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@",data2);
NSData *data3=[@"World" dataUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@",data3);
NSData *dataImage=UIImagePNGRepresentation([UIImage imageNamed:@"Hello.png"]);
NSLog(@"%@",dataImage);


NSMutableData *mdata=[NSMutableData dataWithData:data2];
[mdata appendData:data];
[mdata appendData:data3];
[mdata appendData:data];
[mdata appendData:dataImage];
NSLog(@"%@",mdata);

由此,我得到了具有格式 Hello$World$Image 的字节的 mdata 变量,

现在我想要反转这件事,并希望将 Hello 作为 string1,将 World 作为 String2,并将 Image 存储在某个路径中,但我没有得到如何解析“$”的 NSData 并取出不同的组件。任何帮助将不胜感激。提前致谢

最佳答案

鉴于您对 $ 感到困惑的评论分隔格式,请引用 Binary Data Programming Guide它描述了如何从 NSData 中提取二进制数据.一、创建$分隔 NSData ,你可以这样做:

NSString *path = [[NSBundle mainBundle] pathForResource:@"Hello" ofType:@"png"];
NSData *imageData = [NSData dataWithContentsOfFile:path];

NSMutableData *data = [NSMutableData data];

[data appendData:[@"Hello" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"$" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"World" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"$" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:imageData];

然后,要提取这两个字符串和图像,您可以:
NSUInteger len = [data length];

NSString *delimiterString = @"$";
NSData *delimiterData = [delimiterString dataUsingEncoding:NSUTF8StringEncoding];

NSRange firstDelimiterRange = [data rangeOfData:delimiterData
                                        options:0
                                          range:NSMakeRange(0, len)];

NSUInteger firstDelimiterIndex = firstDelimiterRange.location;
NSAssert(firstDelimiterIndex != NSNotFound, @"First delimiter not found");

NSRange secondDelimiterRange = [data rangeOfData:delimiterData
                                         options:0
                                           range:NSMakeRange(firstDelimiterIndex + 1, len - firstDelimiterIndex - 1)];

NSUInteger secondDelimiterIndex = secondDelimiterRange.location;
NSAssert(secondDelimiterIndex != NSNotFound, @"Second delimiter not found");

NSData   *subdata1 = [data subdataWithRange:NSMakeRange(0, firstDelimiterIndex)];
NSString *string1  = [[NSString alloc] initWithData:subdata1 encoding:NSUTF8StringEncoding];
NSAssert(string1, @"string1 not found");

NSData   *subdata2 = [data subdataWithRange:NSMakeRange(firstDelimiterIndex + 1, secondDelimiterIndex - firstDelimiterIndex - 1)];
NSString *string2  = [[NSString alloc] initWithData:subdata2 encoding:NSUTF8StringEncoding];
NSAssert(string2, @"string2 not found");

NSData   *subdata3 = [data subdataWithRange:NSMakeRange(secondDelimiterIndex + 1, len - secondDelimiterIndex - 1)];
UIImage  *image    = [UIImage imageWithData:subdata3];
NSAssert(image, @"valid image not found");

下面我的原始答案集中在存储两个字符串和二进制图像的可能更好的方法上。鉴于您随后的评论,也许上面的丑陋代码可能对您有用,但我会保留我的原始答案以供将来引用。

几个想法:
  • 如果您只处理字符串(保证其中没有 $),您可以构造您的 NSData像这样:
    NSData *data=[@"$" dataUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"%@",data);
    NSData *data2=[@"Hello" dataUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"%@",data2);
    NSData *data3=[@"World" dataUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"%@",data3);
    
    NSMutableData *mdata=[NSMutableData dataWithData:data2];
    [mdata appendData:data];
    [mdata appendData:data3];
    NSLog(@"%@",mdata);
    

    然后你可以像这样提取字符串:
    NSString *fullString = [[NSString alloc] initWithData:mdata encoding:NSUTF8StringEncoding];
    NSArray  *components = [fullString componentsSeparatedByString:@"$"];
    NSLog(@"components = %@", components);
    

    但是,您不能使用 $处理图像时使用分隔符,因为您无法保证您的 dataImage可能没有 0x24字节。
  • 如果您绝对必须使用 $定界符,那么您必须对图像数据进行一些编码(例如通过base64),以确保它不会出现您的定界符。例如:
    // fill `NSData` with contents of the image data
    
    NSString *path = [[NSBundle mainBundle] pathForResource:@"Hello" ofType:@"png"];
    NSData *data = [NSData dataWithContentsOfFile:path];
    
    NSString *imageBase64String;
    
    // base64 encode the binary data into a string format
    
    if ([data respondsToSelector:@selector(base64EncodedStringWithOptions:)]) {
        imageBase64String = [data base64EncodedStringWithOptions:0]; // iOS 7+
    } else {
        imageBase64String = [data base64Encoding];                   // pre-iOS7
    }
    
    NSArray *array = @[@"Hello", @"World", imageBase64String];
    NSString *finalString = [array componentsJoinedByString:@"$"];
    NSData *finalData = [finalString dataUsingEncoding:NSUTF8StringEncoding];
    

    显然,如果您在将图像添加到 $ 时对图像进行 base-64 编码。分隔 NSData ,然后在另一端,您必须将 base-64 字符串解码回另一端的图像。但希望这能说明这个想法。
  • 在您随后的评论中,您说您正在通过此练习与服务器交换图像。通常,开发人员更喜欢使用成熟的格式(如 JSON 或 XML)与服务器交换数据。例如,考虑 array我之前的示例中的对象,然后您可以创建一个 NSData JSON 表示为
    NSError *error = nil;
    NSData *finalData = [NSJSONSerialization dataWithJSONObject:array options:0 error:&error];
    NSAssert(finalData, @"Unable to dataWithJSONObject: %@", error);
    

    这将生成如下所示的有效负载:
    ["Hello","World","iVBORw0KGgoAAAANSUh ... +Jyutq4AAAAASUVORK5CYII="]
    

    或者,更好的是,您可以使用字典(它可以明确每个元素的功能用途),但希望您能明白:考虑使用完善的标准,如 JSON,为您的服务器创建有效负载。
  • 虽然您随后的评论明确表明您这样做是为了与服务器交换图像,但如果您试图将这三个对象(两个字符串和一个图像)放入 NSData要在您的应用程序中本地保存,更有效的机制是使用存档。因此,要创建一个 NSData存档,您可以:
    NSArray *array = @[@"Hello", @"World", [UIImage imageNamed:@"Hello.png"]];
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:array];
    

    然后,要从此文件中提取结果:
    NSArray *results = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    

    如需更多信息,请参阅 Archives and Serializations Programming Guide .

    但是鉴于您对希望将其发送到服务器的评论,存档可能不是正确的解决方案。
  • 关于ios - 从 NSData : NSData Parsing 中查找不同的组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20761012/

    相关文章:

    c++ - 将所有 nsdata 字节复制到 char* 错误中

    ios - 继续错误对象

    IOS10 - 在自定义 inputView 中使用 CollectionView

    ios - 如何在 Swift 中获取相对于 UIWindow 的 UIBarButtonItem 的框架?

    ios - GDB/LLDB 在指定模块/共享库的所有函数处中断

    java - 使用 Jackson 解析没有标识符的 JSON 对象

    parsing - 确定 Cobol 编码风格

    python - python中个人字典的命名实体识别

    ios - 快速 gzip 数据到字符串问题

    string - 无法转换从本地文件读取的 NSData 并在 Swift 中输出为字符串