#c# #serialization #utf-8
#c# #сериализация #utf-8
Вопрос:
У меня есть довольно простой класс, который содержит несколько примитивных типов и несколько коллекций, содержащих в основном перечисления. Теперь мне нужно сериализовать этот объект до минимально возможного размера, совместимого с UTF8.
Это класс, который мне нужно сериализовать
public class Context
{
public Hashtable UserModuleRoles { get; set; }
public Dictionary<string, object> CustomSettings { get; set; }
public int Uid { get; set; }
public int Id { get; set; }
public int ActiveId { get; set; }
public byte Default { get; set; }
public SetEnum Ident { get; set; }
public string Name { get; set; }
public sbyte State { get; set; }
public DateTime Date { get; set; }
}
.
Вот как я сериализую объект
public string Serialize(object serializeObject)
{
MemoryStream stream = new MemoryStream();
BinaryFormatter b = new BinaryFormatter();
b.Serialize(stream, serializeObject);
byte[] data = stream.ToArray();
stream.Dispose();
stream = new MemoryStream();
using (ZipFile zip = new ZipFile())
{
zip.AddEntry("data", data);
zip.Save(stream);
}
data = stream.ToArray();
stream.Dispose();
return Convert.ToBase64String(data);
}
В моей первой попытке я сериализую объект, заархивирую это содержимое (примерно на 1/3 меньше) и преобразую его в строку base64. Но у base64 довольно большие накладные расходы в 1/3, и я знаю, что есть base128, но я не знаю, с чего начать, и мой поиск кодировки base128 оказался безуспешным.
-
Или есть какой-либо другой способ сделать это?
-
И если нет, то каков наилучший способ
сделать это как base128?
Редактировать:
Я тестировал класс ObjectStateFormatter со всем объектом «Context», что приводит к увеличению на 8 байт и замедлению сериализации / десериализации. Может быть, мне нужно было использовать это только для свойств, а не для всего класса?
Комментарии:
1. Что вы имеете в виду, «совместимый с UTF-8»?
2. Результат будет сохранен в файле cookie, и, насколько я знаю, UTF-8 здесь является стандартом
Ответ №1:
Что ж, base128 не так уж и сложно, если вы знаете, как выполняется base64. Голландская википедия хорошо описывает процесс (перевела его для вас):
- Преобразовать данные в двоичный файл.
- Продолжайте брать фрагменты по 7 бит (2 ^ 7 = 128)
- Преобразуйте эти 7 бит в целое число.
- Найдите это целое число в таблице перевода, которую вы определили, и добавьте найденный символ к строке base128.
Эта таблица перевода содержит 128 совместимых символов UTF8, например:
0: a
1: b
..
25: z
26: 0
Единственное требование заключается в том, чтобы таблица перевода была одинаковой как у отправителя, так и у получателя.
Комментарии:
1. Спасибо! Это поможет мне в этом случае. Но все еще остается вопрос, является ли это лучшим решением или если есть лучшее.
2. Мы не можем сказать вам, является ли это «лучшим решением», с которым вы не предоставили нам достаточно для работы.
3. Хорошо, я опубликовал код метода serialize и класс для сериализации. Я не знаю, что еще вы имеете в виду.
Ответ №2:
Попробуйте использовать objectstateformatter
вместо BinaryFormatter
, возможно, это даст вам меньший размер. Все зависит от данных, которые вы сериализуете.
Комментарии:
1. Хорошо, я попробую это завтра и сравню размер. Самой большой частью будет хэш-таблица, которая содержит только перечисления. Или, может быть, не самый большой, но часть с наибольшим количеством значений.
2. Хорошо, наконец-то я это протестировал. В моем простом тесте он был примерно на 8 байт больше обычного потока байтов и намного медленнее. Я не знаю почему, потому что все типы данных внутри объекта полностью совместимы с классом objectstateformatter, согласно msdn. Возможно, я получу лучшие результаты, если я сериализую только значения и ничего из объекта. Но тогда я окажусь в более чем десяти отдельных потоках и … нет, для меня это звучит не очень хорошо. Или я что-то пропустил в своем тесте?