Эффективный способ сжатия NSDictionary в NSData

Я использую BTLE для записи данных в одну из характеристик периферийного устройства. Я хотел отправить NSDictionary в эти характеристики. Поскольку существует ограничение в 130 байтов данных, отправляемых через BTLE, мне нужен эффективный способ сжатия NSDictionary в NSData, а затем отправки. Я использую приведенный ниже фрагмент кода, который превышает лимит. Есть идеи?

NSDictionary *aDict = @{ @"Value1": @"sadsadasdasdsadqwwqsadasd",
                         @"Value2": @"10",
                         @"Value3": @"12" };
NSData *aData = [NSKeyedArchiver archivedDataWithRootObject:aDict];
NSLog(@"Data Size = %@",
        [NSByteCountFormatter stringFromByteCount:aData.length
                                       countStyle:NSByteCountFormatterCountStyleFile]);

person Abhinav    schedule 14.07.2013    source источник
comment
Проверь это. Это должно помочь. stackoverflow .com/questions/3157356/   -  person Abdullah Shafique    schedule 14.07.2013
comment
Вы можете попытаться сжать NSData, как описано здесь: stackoverflow.com/a/234099/475052   -  person Carl Veazey    schedule 14.07.2013
comment
Не знаю, какое представление использует NSKeyedArchiver — вероятно, JSON будет более компактным. В любом случае, в представлении вряд ли будет много газа, поэтому вам придется прибегнуть к некоторому сжатию данных, если вы действительно хотите сжать все воедино.   -  person Hot Licks    schedule 14.07.2013
comment
(Обычный старый JSON будет представлять приведенное выше примерно в 65 байтах — по сути, такой же длины, как ваш оператор инициализации, за вычетом всех символов @.)   -  person Hot Licks    schedule 14.07.2013


Ответы (1)


Я не думаю, что попытки использовать какую-либо форму сжатия будут эффективными или даже улучшат вообще в этом масштабе, потому что все алгоритмы сжатия работают лучше всего, когда у них есть много данных для работы, и, следовательно, много дубликатов и шаблонов для поиска. Когда весь размер ваших данных составляет 130 байт, любая форма zip-сжатия на самом деле не подходит.


Если ваш словарь будет содержать только значения списка свойств (массивы, словари, строки, числа), вы можете использовать сериализацию JSON вместо NSKeyedArchiver:

NSData *JSONData = [NSJSONSerialization dataWithJSONObject:anObject
                                                   options:0
                                                     error:nil];

Это сразу делает выходные данные намного короче в вашем случае:

NSDictionary *aDict = @{ @"Value1": @"sadsadasdasdsadqwwqsadasd",
                         @"Value2": @"10",
                         @"Value3": @"12" };

NSData *aData = [NSKeyedArchiver archivedDataWithRootObject:aDict];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:aDict
                                                   options:0
                                                     error:nil];

NSLog(@"NSKeyedArchiver Data Size = %@, JSON Data Size = %@",
      [NSByteCountFormatter stringFromByteCount:aData.length
                                     countStyle:NSByteCountFormatterCountStyleFile],
      [NSByteCountFormatter stringFromByteCount:jsonData.length
                                     countStyle:NSByteCountFormatterCountStyleFile]
      );

Размер данных NSKeyedArchiver = 380 байт, размер данных JSON = 66 байт

Как видите, сериализованные данные JSON почти в 6 раз меньше, чем сериализованные данные NSKeyedArchiver, и легко умещаются в 130 байт. И самое лучшее, это всего лишь одна строка кода.

ОБНОВЛЕНИЕ: просто чтобы еще немного втереть :), вот данные, которые создает NSKeyedArchiver (добавлено как изображение, потому что оно содержит много «недопустимых» символов, которые я не мог скопировать и вставить):

Данные NSKeyedArchiver

Как вы можете видеть, он содержит много бесполезных данных, которые вам на самом деле не нужны (выделены синим цветом), это в основном только для того, чтобы предоставить NSKeyedUnarchiver достаточно информации, чтобы иметь возможность разархивировать ее позже.

Теперь давайте посмотрим на данные JSON:

{"Value3":"12","Value2":"10","Value1":"sadsadasdasdsadqwwqsadasd"}

Вот и все. Одна линия. 66 байт. Из них 19 байтов не являются вашими значениями. Другими словами, 71% этих данных JSON — это ваши значения, а остальное — это, так сказать, разметка. Между тем, в данных NSKeyedArchiver ваши значения составляют, подождите, 12% результата. Я думаю, вы можете ясно видеть, какой из них более эффективен для хранения здесь.

person Greg    schedule 14.07.2013
comment
Имеет смысл. Спасибо, что так изящно объяснили! - person Abhinav; 16.07.2013