【问题标题】:Obtain NSString from NSData arriving separately从分别到达的 NSData 中获取 NSString
【发布时间】:2012-01-25 12:18:35
【问题描述】:

我正在编写一个程序,它将 NSData 转换为具有多字节编码的 NSString。 转换本身很容易,但问题是 NSData 是单独到达的(数据按顺序到达)。 就像

- (void) dataArrived:(NSData*) data{
    NSString* mystr = [[[NSString alloc] initWithData:data encoding:NSShiftJISStringEncoding] autorelease];
    // I want to parse string here and show some view as it arrives.
}

如果数据仅包含 8 位字母,则可以,但我正在解析多字节字符串数据。所以我想要做的是将 NSData 从头转换为 NSString 并将无效字节保留到 dataArrived 的下一次调用(最后 1 个字节可能留作 NSShiftJISStringEncoding 的无效字节,因为 SJIS 字母是 1 或 2 个字节)。

我想知道他们是否有任何有用的方法或功能可以做到这一点。 理想的方法可以取 NSData 和 Encoding,返回在 NSData 中找到无效字节序列的位置。

【问题讨论】:

  • 我的回答没有解决您的问题吗? ;-)

标签: objective-c encoding nsstring nsdata


【解决方案1】:

由于 Shift JIS 编码为 1 或 2 个字节,您可以假设:

  • 所有未处理的数据都是有效的 Shift JIS 字符串
  • 或第一个长度为 1 的字节是有效的 Shift JIS 字符串

所以,我们可以使用NSMutableData 缓冲区并像这样处理数据:

- (void)dataArrived:(NSData*)data
{
    [_mutableData appendData:data];
    NSUInteger length = [_mutableData length];
    NSString *string = [[[NSString alloc] initWithData:_mutableData
                                              encoding:NSShiftJISStringEncoding] autorelease];

    if ( ! string && length )
    {
        // try without the last byte
        --length;
        string = [[[NSString alloc] initWithBytes:data.bytes
                                           length:length
                                         encoding:NSShiftJISStringEncoding] autorelease];
    }

    if ( ! string && length )
    {
        // we have a problem: the data are invalid
        return;
    }

    // remove processed bytes
    [_mutableData replaceBytesInRange:NSMakeRange(0, length) withBytes:NULL length:0];

    // now, we can append string
}

【讨论】:

  • 这对于 SJIS 编码看起来不错。我想要任何编码的通用解决方案,但我将它用于目前正在研究的 SJIS。
  • 恐怕没有优雅的通用解决方案。由于大多数编码使用 1 到 4 个字节来编码字符,因此您可以循环直到获得有效字符串或长度为零。
【解决方案2】:

您是否考虑过收集所有数据然后一次全部解码?如果您不必处理大量数据,这将比您建议的方法简单得多。

【讨论】:

  • 是的。正如我已经评论的那样,等待所有数据到来的另一个答案可能需要很长时间,我想避免它。
【解决方案3】:

如何存储所有接收到的数据,然后从更新的数据中重新创建字符串?

@interface StringReceiver {
    NSMutableData *_allData;
}
@property (retain, readonly) NSString *string;
- (void)processData:(NSData *)d;
@end

@implementation StringReceiver
- (id)init {
    self = [super init];
    if(self != nil) {
        _allData = [NSMutableData new];
    }
    return self;
}

- (void)dealloc {
    [_allData release];
    [super dealloc];
}

- (NSString *)string {
    NSString *s;
    s = [[NSString alloc] initWithData:_allData encoding:NSShiftJISStringEncoding];
    return [s autorelease];
}

- (void)processData:(NSData *)myData {
    [_allData appendData:myData];
}
@end

现在每次调用-[StringReceiver processData:] 时,都可以调用-[StringReceiver string] 来获取更新的字符串。

【讨论】:

  • 我已经实现了你提出的那个。由于用户体验,我想尽快显示从数据中获得的字符串(等待所有数据到来可能需要很长时间)
  • 这就是为什么每次你打电话给-pocessData:,你都可以打电话给-string。这样,您可以在每次更新后向用户展示您所获得的内容。
  • 哦,我可能误解了你的建议。这意味着每次我调用“字符串”方法时,我都可以获得到目前为止收到的字符串...
  • 是的,我想解码不完整的数据对NSString来说不是问题。
  • 谢谢。这是一种选择。重复从 NSData 转换为相同字节的 NSString 可能会导致性能问题,但值得尝试。
猜你喜欢
  • 2011-03-02
  • 2011-08-31
  • 2012-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-17
相关资源
最近更新 更多