【问题标题】:NSData getBytes Randomly Returns GarbageNSData getBytes 随机返回垃圾
【发布时间】:2014-08-05 14:38:31
【问题描述】:

我正在尝试在 iOS 应用中保存和加载自定义文件格式。该格式存储各种数据,但其中包括用户为地图输入的名称。我随机发现,当我尝试读取此地图名称(在文件中存储为chars)时,我的 NSData 对象将读取垃圾。这是我读取地图名称的代码(start 已经设置为正确的起始位置):

NSData* data = ....;
uint mapNameLength;
char* mapNameChar;
NSString* mapNameString;

[data getBytes:&mapNameLength range:NSMakeRange(start, 4)];
start += 4;
mapNameChar = (char *)malloc(sizeof(char) * mapNameLength);
[data getBytes:mapNameChar range:NSMakeRange(start, mapNameLength)];
mapNameString = [NSString stringWithUTF8String:mapNameChar];

NSLog(@"mapNameLength: %u, mapNameChar: %s, Map name string: %@", mapNameLength, mapNameChar, mapNameString);

如您所见,我正在读取名称的长度,然后读取许多 char 值,然后将其转换为 NSString。这是 NSLog 工作时的输出(我只是敲了几下键盘以取长名):

mapNameLength: 49, mapNameChar: kandfianeifniwbvuandivbwirngiwnrivnwrivnwidnviwdv, Map name string: kandfianeifniwbvuandivbwirngiwnrivnwrivnwidnviwdv

这是 NSLog 不工作时的输出:

mapNameLength: 49, mapNameChar: kandfianeifniwbvuandivbwirngiwnrivnwrivnwidnviwdvfi?p?, Map name string: (null)

那些“?”实际上是这里不显示的特殊字符,所以我添加了它们。第一个是“ETX”,第二个是 Sublime Text 中的“SOH”。

要创建文件,这就是我正在做的事情:

NSString* mapName = ....;
uint mapNameLength = (uint)mapName.length;
NSMutableData* data = ....;
//...
//Write file type and version here
//...
[data appendBytes:&mapNameLength length:4];
[data appendData:[mapName dataUsingEncoding:NSUTF8StringEncoding]];
//...
//Write other stuff
//...

NSString* path = [FileManager applicationDocumentsDirectory];
path = [path stringByAppendingFormat:@"/%@", fileName];
BOOL success = [data writeToFile:path options:NSDataWritingAtomic error:&error];

我只写过一次文件,所以我知道数据总是一样的。那么,为什么我的数据对象有时会从中获取随机字节?

【问题讨论】:

    标签: ios objective-c nsdata


    【解决方案1】:

    我不确定,但是我不认为您正在存储终止 NUL 字符,因此您需要在读取字符串后向缓冲区添加一个:

    mapNameChar = (char *)malloc(sizeof(char) * (mapNameLength + 1));   // Add +1
    [data getBytes:mapNameChar range:NSMakeRange(start, mapNameLength)];
    mapNameChar[mapNameLength] = '\0';            // Terminate with NUL
    mapNameString = [NSString stringWithUTF8String:mapNameChar];
    

    最好还是忘掉malloc() 和C-String,直接从NSData 对象创建NSString

    mapNameString = [[NSString alloc] initWithBytes:(const char *)([data bytes]) + start
                                             length:mapNameLength
                                           encoding:NSUTF8StringEncoding];
    

    【讨论】:

    • 为了逻辑正确性应该是sizeof(char) * (mapNameLength + 1)
    • 啊哈!认为这很愚蠢;)要么是固定的,要么是我刚刚尝试了 50 次真的很幸运。谢谢你让我头疼!
    • @MikeBoch 请查看更新后的答案;你可以忘记malloc()
    • 如果您希望能够对其进行指针运算,您需要将 [data bytes] 转换为具体的东西,例如 const char *...
    • @Droppy 是的,我明白了。我不确定如何只用一部分字节创建一个字符串。没想到只是添加到指针!这是一个更好的方法。谢谢!
    猜你喜欢
    • 2013-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-04
    • 2015-06-27
    • 2016-07-12
    • 1970-01-01
    相关资源
    最近更新 更多