如何从XCode

时间:2016-06-17 17:15:18

标签: objective-c xcode parsing nsstream nsinputstream

所以我的应用程序按以下方式工作:

  1. iPod不断发送NSDictionaries,其中包含:以JPEG编码的图像和一些图像属性作为NSStrings。
  2. NSDictionary使用NSPropertyListSerialization编码,格式为BinaryFormat_v1_0,并通过NSStream以1024字节的数据包发送到运行OSX上的应用程序的中央计算机。
  3. OSX应用程序接收数据包,不断附加到单个NSMutableData对象,直到它看到下一个NSData对象的第一个数据包(我发现二进制格式为'bplist')。
  4. 通过调用NSPropertyListSerialization,NSData将转换回OSD应用程序使用的NSDictionary。
  5. NSData成功转换(或不成功)后,NSData对象将重新设置为零以开始读取下一轮数据包。
  6. 还有一些注意事项:NSInputStream和NSOutput流都在NSDefaultRunLoopMode中各自设备的currentRunLoop上运行。

    运行此过程时,有时转换回NSDictionary工作正常,没有错误(大约1/3次尝试),但其他时候转换返回此错误:

      

    错误:无法将NSData转换为NSDict:错误域= NSCocoaErrorDomain代码= 3840“第1行的意外字符b”UserInfo = {NSDebugDescription =第1行的意外字符b,kCFPropertyListOldStyleParsingError =错误域= NSCocoaErrorDomain代码= 3840“转换字符串失败了。“ UserInfo = {NSDebugDescription =字符串转换失败。}}

    以下是解析流中数据的程序部分:

    ...处理流事件的方法:

    -(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {
    switch(eventCode) {
        case NSStreamEventHasBytesAvailable: {
    
            uint8_t buf[1024];
            unsigned int len = (unsigned)[(NSInputStream *)aStream read:buf maxLength:1024];
    
            if(len) {
                [self handleEventBuffer:buf WithLength:len];
            }
    ...
    

    ...以及处理数据的方法:

    -(void)handleEventBuffer:(uint8_t*)buf WithLength:(unsigned int)len {
    ...
    NSString *bufStr = [NSString stringWithFormat:@"%s",(const char*)buf];
            if ([bufStr containsString:@"bplist00"] && [self.cameraData length] > 0) {
                // Detected new file, enter in all the old data and reset for new data
                NSError *error;
                NSDictionary *tempDict = [[NSDictionary alloc] init];
    
                tempDict = [NSPropertyListSerialization propertyListWithData:self.cameraData
                                                                 options:0
                                                                  format:NULL
                                                                   error:&error];
    
                if (error != nil) {
                    // Expected good file but no good file, erase and restart
                    NSLog(@"Error: Failed to convert NSData to NSDict : %@", [error description]);
                    [self.cameraData setLength:0];
                } 
    ...
                [self.cameraData setLength:0];
                [self.cameraData appendBytes:buf length:len];
    
            } else {
                // Still recieving data
                [self.cameraData appendBytes:buf length:len];
            }
    

    所以,我得到的问题是:

    • 如何修复我的解析方法,以便为我提供可靠的结果,而这些结果不会随机无法转换?
    • OR是否有更好的方法来解析缓冲流用于此目的?
    • 或者我只是在做一些愚蠢或遗漏的事情?

1 个答案:

答案 0 :(得分:1)

您似乎依赖于对流的每次写入,导致相同大小的匹配读取,您知道这是NSStream保证的吗?如果没有,则任何读取都可能包含两个(或更多)编码字典的一部分,您将看到您看到的解析错误。

替代方法:

对于要发送的每个编码字典:

写完:

  1. 发送一条消息,其中包含随后的编码字典的字节大小。
  2. 将编码的字典写成块,最后一个块可能很短
  3. 重复
  4. 阅读结束:

    1. 读取大小消息,指定其确切长度(以字节为单位)。
    2. 以块的形式读取编码的字典,确保只读取(1)报告的字节数。
    3. 重复。
    4. 如果您使用的是可靠的通信流,则应该可以让您可靠地读取每个编码的字典。它避免你试图找出每个编码字典之间的边界,因为该信息是你的协议的一部分。

      HTH