в основном, у меня есть таблица Хаффмана как
std::map<std::string, char> ciMap;
Где строка - это битовый шаблон, а char - значение, представленное указанным шаблоном. Проблема в том, как сохранить это как заголовок моего сжатого файла, чтобы я мог снова построить ту же карту, когда захочу ее декодировать?
Попытка сохранить его как двоичный:
size_t mapLen = ciMap.size();
outFile.write(reinterpret_cast<char*>(&mapLen), sizeof(size_t));
outFile.write(reinterpret_cast<char*>(&ciMap), sizeof(ciMap));
А позже построение с:
inFile.read(reinterpret_cast<char*>(&mapLen), sizeof(size_t));
inFile.read(reinterpret_cast<char*>(&ciMap), sizeof(mapLen));
Не работает, я получаю ошибку инициализации строки ... что-то связано с NULL. Какие-либо предложения? Если у вас есть лучший способ хранения битов и значений, я хотел бы услышать.





Отличный вопрос. Проблема здесь в том, что контейнеры по умолчанию не поддерживают сериализацию - вы должны написать это самостоятельно, это больно, но возможно.
Вот как можно преобразовать std::map в текстовый формат. Вы можете адаптировать его для записи в любой нужный вам двоичный формат. Просто замените оператор << на reads и writes.
template<typename K, typename V>
std::ostream &operator << (std::ostream &out, const std::map<K,V> &map) {
out << "map " << map.size() << "\n";
for (typename std::map<K,V>::const_iterator i = map.begin(); i != map.end(); ++i) {
out << (*i).first << "\n" << (*i).second << "\n";
}
return out;
}
template<typename K, typename V>
std::istream &operator >> (std::istream &in, std::map<K,V> &map) {
std::string mapkeyword;
size_t num;
in >> mapkeyword >> num;
for (size_t i = 0; i < num; ++i) {
K key; V value;
in >> key >> value;
map[key] = value;
}
return in;
}
Вы не можете просто сериализовать двоичные значения на диск таким образом. Представление в памяти - это не просто непрерывный блок памяти, и даже если бы это было так, оно, скорее всего, будет содержать указатели, относящиеся к адресу блока.
Вам нужно перебирать карту и сериализовать каждый элемент индивидуально. Затем, чтобы вернуть их, вы реконструируете карту, считывая элементы с диска один за другим и повторно вставляя их в карту.
Вы можете сделать это сами, а можете сделать это с помощью boost: http://www.boost.org/doc/libs/1_37_0/libs/serialization/doc/index.html. В настоящее время вы пытаетесь просто просматривать карту как обычный старый тип данных, что, по сути, означает, что это тип данных C. Но это не так, поэтому не удается сохранить / загрузить. Boost сериализация делает это правильно. Посмотри на это. Если вы не хотите его использовать, вы можете сделать что-то вроде этого:
typedef std::map<std::string, char> my_map;
my_map ciMap;
// saving
std::ofstream stream("file.txt");
for(my_map::const_iterator it = ciMap.begin(); it != ciMap.end(); ++it) {
stream << it->first << " " << it->second << std::endl;
}
// loading
char c;
std::string bits;
std::ifstream stream("file.txt");
while(stream >> bits >> c)
ciMap.insert(std::make_pair(bits, c));
Обратите внимание, что приведенное выше требует некоторых изменений, если сохраненные символы также могут быть пробельными символами. Из-за этого, вероятно, лучше сначала преобразовать в int перед записью, а затем читать как int при загрузке. На самом деле, я рекомендую повысить сериализацию и увеличить iostreams (http://www.boost.org/doc/libs/1_37_0/libs/iostreams/doc/index.html), который включает поток сжатия, который также может прозрачно сжимать ваши данные.