C ++ Huffman Code Header - PullRequest
       13

C ++ Huffman Code Header

2 голосов
/ 09 декабря 2008

в основном, у меня есть стол Хаффмана как

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. Какие-либо предложения? Если у вас есть лучший способ хранения битов и значений, я бы хотел услышать.

Ответы [ 3 ]

4 голосов
/ 09 декабря 2008

Вы можете сделать это самостоятельно, или вы можете сделать это с надстройкой: http://www.boost.org/doc/libs/1_37_0/libs/serialization/doc/index.html. В настоящее время вы пытаетесь просто просмотреть карту как простой старый тип данных, что по сути означает, что это тип данных C. Но это не так, поэтому не удается сохранить / загрузить. повышение сериализации делает это правильно. Посмотри на это. Если вы не хотите его использовать, вы можете сделать что-то вроде этого:

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),, который включает поток сжатия, который также может прозрачно сжимать ваши данные.

3 голосов
/ 09 декабря 2008

Таким способом нельзя просто сериализовать двоичные значения на диск. Представление в памяти - это не просто непрерывный блок памяти, и даже если бы оно было, оно, вероятно, будет содержать указатели, относящиеся к адресу блока.

Вам нужно перебрать карту и сериализовать каждый элемент по отдельности. Затем, чтобы вернуть их обратно, вы восстанавливаете карту, считывая элементы с диска по одному и вставляя их в карту.

2 голосов
/ 09 декабря 2008

Отличный вопрос. Проблема здесь в том, что контейнеры по умолчанию не поддерживают сериализацию - вы должны написать это самостоятельно, это больно, но это возможно.

Вот как вы можете сериализовать 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;
}
...