2014-08-05 2 views
1

Я пытаюсь сохранить и загрузить пользовательский формат файла в приложении iOS. Формат хранит различные данные, но среди них есть имя, которое пользователь вводил для карты. Я обнаружил, что наугад, когда я пытаюсь прочитать это имя карты (сохранено как char s в файле), мой объект NSData будет читать мусор. Вот мой код для чтения имени карты (start уже установлена ​​в правильном место старта):NSData getBytes Randomly Returns Garbage

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», второй - «SOH» в Sublime Text.

Чтобы создать файл, это то, что я делаю:

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

Я только написал файл один раз, так что я знаю, что данные всегда одинаковы. Почему же тогда мой объект данных иногда получает от него случайные байты?

ответ

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]; 
+1

Должно быть 'SizeOf (Char) * (mapNameLength + 1)' для логической правильности. – tia

+0

@tia Да; Спасибо. – Droppy

+0

Aha! Понял, что это будет что-то глупое;) Либо это исправлено, либо мне повезло, что 50 раз я просто попробовал. Спасибо, что спасли мне эту головную боль! –