Как да съхранявате 128 бита UUID в 16 байта ASCII NSString

Искам да запазя 128-битов UUID в 16-байтов низ, който ще се съхранява в Core Data като атрибут на индекс на моя ManagedObject, за да се гарантира ефективността на вмъкване и избор.

Има ли някакъв начин да съхраните 128-битов UUID в 16-байтов ASCII низ? Ако има, как да конвертирате между 32-байтов UUID низ и 16-байтов ASCII низ?

Опитах се да съхраня CFUUIDBytes в низ, използвайки кода по-долу, но стойността се промени след генерирането на низа. (ако някоя байтова стойност е > 127, стойността й се променя в генерирания низ)

CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
CFUUIDBytes uuidBytes = CFUUIDGetUUIDBytes(uuidRef);
NSString *utf8String = [NSString stringWithFormat:@"%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", 
                            uuidBytes.byte0, uuidBytes.byte1, uuidBytes.byte2,
                            uuidBytes.byte3, uuidBytes.byte4, uuidBytes.byte5,
                            uuidBytes.byte6, uuidBytes.byte7, uuidBytes.byte8,
                            uuidBytes.byte9, uuidBytes.byte10, uuidBytes.byte11,
                            uuidBytes.byte12, uuidBytes.byte13, uuidBytes.byte14,
                            uuidBytes.byte15];

person Cable W    schedule 06.07.2012    source източник
comment
Необходими са 16 байта за съхраняване на 128 бита, но те не могат да бъдат ASCII (или UTF-8), тъй като са двоични; ще трябва да използвате поне 32 байта.   -  person trojanfoe    schedule 06.07.2012
comment
Благодаря за коментара! Бихте ли обяснили повече защо не може да се съхранява в ASCII или UTF-8? Всъщност моят тест също показва това, което предложихте, но просто не знам защо.   -  person Cable W    schedule 06.07.2012
comment
Те не могат да се съхраняват в ASCII/UTF-8, тъй като процесът на низоване им изисква всеки байт да се съхранява в 2 байта. Може би можете да използвате двоичната форма в Core Data (не знам)?   -  person trojanfoe    schedule 06.07.2012


Отговори (1)


Използвайте тази категория в NSString с любезното съдействие:

   static unichar x (unsigned int); 

@implementation NSString (TWUUID) 

+ (NSString*) stringWithUniqueId 
{ 
    CFUUIDRef uuid = CFUUIDCreate(NULL); 
    CFUUIDBytes b = CFUUIDGetUUIDBytes(uuid); 
    unichar unichars[22]; 
    unichar* c = unichars; 
    *c++ = x(b.byte0 >> 2); 
    *c++ = x((b.byte0 & 3 << 4) + (b.byte1 >> 4)); 
    *c++ = x((b.byte1 & 15 << 2) + (b.byte2 >> 6)); 
    *c++ = x(b.byte2 & 63); 
    *c++ = x(b.byte3 >> 2); 
    *c++ = x((b.byte3 & 3 << 4) + (b.byte4 >> 4)); 
    *c++ = x((b.byte4 & 15 << 2) + (b.byte5 >> 6)); 
    *c++ = x(b.byte5 & 63); 
    *c++ = x(b.byte6 >> 2); 
    *c++ = x((b.byte6 & 3 << 4) + (b.byte7 >> 4)); 
    *c++ = x((b.byte7 & 15 << 2) + (b.byte8 >> 6)); 
    *c++ = x(b.byte8 & 63); 
    *c++ = x(b.byte9 >> 2); 
    *c++ = x((b.byte9 & 3 << 4) + (b.byte10 >> 4)); 
    *c++ = x((b.byte10 & 15 << 2) + (b.byte11 >> 6)); 
    *c++ = x(b.byte11 & 63); 
    *c++ = x(b.byte12 >> 2); 
    *c++ = x((b.byte12 & 3 << 4) + (b.byte13 >> 4)); 
    *c++ = x((b.byte13 & 15 << 2) + (b.byte14 >> 6)); 
    *c++ = x(b.byte14 & 63); 
    *c++ = x(b.byte15 >> 2); 
    *c = x(b.byte15 & 3); 
    CFRelease(uuid); 
    return [NSString stringWithCharacters: unichars length: 16];
} 
@end

unichar x (unsigned int c)
{
    if (c < 26) return 'a' + c;
    if (c < 52) return 'A' + c - 26;
    if (c < 62) return '0' + c - 52;
    if (c == 62) return '$';
    return '_';
}


...


    NSLog(@"%u", [[NSString stringWithCString:[[NSString stringWithUniqueId] UTF8String] encoding:NSASCIIStringEncoding] length]);
person CodaFi    schedule 06.07.2012
comment
Благодаря. Но използването на CFUUIDCreateString() може да генерира само 36 байта UUID String. Тъй като бих искал да съхраня UUID като основен идентификатор на моя обект Core Date, искам да е възможно най-кратък (16 байта). - person Cable W; 06.07.2012
comment
Опитах, но изглежда не работи. Можете ли да предоставите работещ пример? работния код, имам предвид. - person Cable W; 06.07.2012
comment
Съжалявам, този код беше неприятен. Опитайте този в моята редакция на действителната публикация. - person CodaFi; 06.07.2012
comment
Опитах и ​​този и тествах резултата. Но изглежда по-лошо от кода, който използвах по-горе. Може би съм погрешил по някакъв начин. Бихте ли могли да тествате кода си и да публикувате работния код? Благодаря - person Cable W; 06.07.2012
comment
Работи, но резултатът все още е 36 байта NSString. Това, което искам, е 16 байта NSString. Но все пак благодаря! - person Cable W; 06.07.2012
comment
Най-накрая сдвоих това нещо до 16 байта. Имайте го. - person CodaFi; 06.07.2012
comment
Причината, поради която не използвам NSData, е, че той се съпоставя към BLOB тип в SQLite (под Core Data), което почти не е сравнимо и е по-малко ефективно от типа TEXT (NSString). Освен това типът Integer в SQLite е 64 бита, което е много по-малко от 128 бита на UUID. Следователно NSString за съжаление е единственият ми избор. - person Cable W; 06.07.2012
comment
Не можете да поставите низ в ново кодиране и да очаквате по-малък размер на същия низ, без да намалите самия низ. Минимумът, който това нещо може да бъде, е 36 байта в UTF-8, така че тук се използва само дължината от 16 байта, за да се запази изискването за пространство, което поискахте. И накрая, този всъщност регистрира 16 байта. - person CodaFi; 06.07.2012
comment
съжалявам, моят тест не може да преобразува низа, генериран с помощта на вашия метод, обратно в оригиналните байтови данни. но благодаря много - person Cable W; 06.07.2012