我正在尝试在iOS应用中保存并加载自定义文件格式。格式存储各种数据,但其中包括用户为地图输入的名称。我随机发现,因为我正在尝试读取这个地图名称(在文件中存储为char
),我的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];
我只写了一次文件,所以我知道数据总是一样的。那么,为什么我的数据对象有时会从中获取随机字节?
答案 0 :(得分:2)
我不确定,但我不认为您正在存储终止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并直接从NSString
对象创建NSData
:
mapNameString = [[NSString alloc] initWithBytes:(const char *)([data bytes]) + start
length:mapNameLength
encoding:NSUTF8StringEncoding];