简体   繁体   English

从NSData中查找不同的组件:NSData解析

[英]Finding Different Components from NSData: NSData Parsing

I am having NSData in format as "Hello$World$Image"($ is used as Delimeter to differentate different part Data) That i have made by using Following Code 我的NSData格式为“Hello $ World $ Image”($用作Delimeter来区分不同的部分数据)我使用以下代码制作

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);

From this, I got mdata variable that is having bytes with format Hello$World$Image, 从这里,我得到了mdata变量,其中包含格式为Hello $ World $ Image的字节,

Now I Want reverse thing of this and want to get Hello as string1, World as String2, and Image to store in some path, But i am not getting How to parse the NSData for "$" and get the different components out. 现在我想要反过来的事情,并希望得到Hello作为string1,World作为String2,和Image存储在某个路径,但我没有得到如何解析NSData为“$”并获得不同的组件。 Any help will be appreciated. 任何帮助将不胜感激。 Thanks in Advance 提前致谢

Given your comment that you're stuck with this $ delimited format, you should refer to the Binary Data Programming Guide which describes how to extract binary data from a NSData . 鉴于您的评论是您坚持使用这种$ delimited格式,您应该参考二进制数据编程指南 ,该指南描述了如何从NSData提取二进制数据。 First, to create the $ delimited NSData , you could do: 首先,要创建$ delimited 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];

Then, to extract these two strings and the image, you could: 然后,要提取这两个字符串和图像,您可以:

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");

My original answer, below, focused on possibly better ways to store two strings and a binary image. 我在下面的原始答案集中在可能更好的方法来存储两个字符串和二进制图像。 Given your subsequent comments, perhaps the ugly code above might work for you, but I'll keep my original answer for future reference. 鉴于您随后的评论,上面的丑陋代码可能对您有用,但我会保留原始答案以供将来参考。


A couple of thoughts: 几点想法:

  1. If you were dealing with just strings (that were guaranteed not to have a $ in them), you could construct your NSData like so: 如果你只处理字符串(保证它们没有$ ),你可以像这样构造你的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); 

    And then you could extract the strings like so: 然后你可以像这样提取字符串:

     NSString *fullString = [[NSString alloc] initWithData:mdata encoding:NSUTF8StringEncoding]; NSArray *components = [fullString componentsSeparatedByString:@"$"]; NSLog(@"components = %@", components); 

    But, you cannot use the $ delimiter when dealing with an image, because you have no assurances that your dataImage might not have a 0x24 byte in it. 但是,在处理图像时不能使用$ delimiter,因为您无法保证dataImage可能没有0x24字节。

  2. If you absolutely have to use the $ delimiter, then you have to do some encoding of your image data (such as via base64), to ensure it cannot have an occurrence of your delimiter in it. 如果你必须使用$ delimiter,那么你必须对你的图像数据进行一些编码(例如通过base64),以确保它不会出现你的分隔符。 For example: 例如:

     // 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]; 

    Clearly, if you base-64 encode the image when you add it to your $ delimited NSData , then at the other end, you have to decode the base-64 string back into an image at the other end. 显然,如果您在将图像添加到$ delimited NSData时对其进行base-64编码,那么在另一端,您必须将base-64字符串解码回另一端的图像。 But hopefully this illustrates the idea. 但希望这说明了这个想法。

  3. In your subsequent comments, you've said that you're going through this exercise to exchange the image with a server. 在随后的评论中,您已经说过要通过此练习与服务器交换图像。 Generally developers prefer to use well-established formats like JSON or XML to exchange data with a server. 通常,开发人员更喜欢使用完善的格式(如JSON或XML)与服务器交换数据。 For example, considering the array object from my previous example, you could then create a NSData with a JSON representation as 例如,考虑到我之前示例中的array对象,您可以创建一个带有JSON表示的NSData

     NSError *error = nil; NSData *finalData = [NSJSONSerialization dataWithJSONObject:array options:0 error:&error]; NSAssert(finalData, @"Unable to dataWithJSONObject: %@", error); 

    That would generate a payload that would look like: 这将生成一个看起来像这样的有效负载:

     ["Hello","World","iVBORw0KGgoAAAANSUh ... +Jyutq4AAAAASUVORK5CYII="] 

    Or, better, you might use a dictionary (which makes the functional purpose of each of the elements clear), but hopefully you get the idea: Consider using a well-established standard, like JSON, for creating your payload for your server. 或者,更好的是,您可以使用字典(这使得每个元素的功能目的都清晰),但希望您明白这一点:考虑使用一个完善的标准,如JSON,为您的服务器创建有效负载。

  4. While your subsequent comments have made it clear that you're doing this to exchange an image with a server, if you were trying to put these three objects, two strings and an image, into a NSData to be saved locally in your app, a more efficient mechanism would be to use an archive. 虽然您的后续评论已明确表示您正在执行此操作以与服务器交换图像,但如果您尝试将这三个对象(两个字符串和一个图像)放入NSData以便在应用程序中本地保存,更有效的机制是使用档案。 Thus, to create a NSData archive, you can: 因此,要创建NSData存档,您可以:

     NSArray *array = @[@"Hello", @"World", [UIImage imageNamed:@"Hello.png"]]; NSData *data = [NSKeyedArchiver archivedDataWithRootObject:array]; 

    Then, to extract the results from this archive: 然后,从此存档中提取结果:

     NSArray *results = [NSKeyedUnarchiver unarchiveObjectWithData:data]; 

    For more information see the Archives and Serializations Programming Guide . 有关更多信息,请参阅“ 存档和序列化编程指南”

    But given your comments about wanting to send this to a server, an archive probably is not the right solution. 但鉴于您对要将其发送到服务器的意见,存档可能不是正确的解决方案。

I think using of NSCoding is good idea in this case. 我认为在这种情况下使用NSCoding是个好主意。 You will need to create class with some properties and implement NSCoding protocol methods. 您将需要创建具有某些属性的类并实现NSCoding协议方法。

See any example for using it, this is first i've found in google, you can use any 看到任何使用它的例子, 是我在谷歌找到的第一个,你可以使用任何

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM