Romeo » 28 июл 2017, 15:46
Предлагаю писать все данные просто в бинарный поток через write. Каждое поле записывать по правилу: сначала длина, потом чек-сумма, потом шифрованные данные. Поднимаем из файла в таком же порядке.
Небольшие наброски кода. Код писался в блокноте, так что могут быть опечатки.
Код: Выделить всё
#include <string>
#include <fstream>
#include <numeric>
#include <algorithm>
#include <functional>
inline unsigned char CheckSum(const std::string& str)
{
const auto sum = std::accumulate(str.cbegin(), str.cend(), 0ul);
// Оставляем только младший байт от всей суммы.
return static_cast<unsigned char>(sum);
}
void WriteString(std: :o fstream& file, const std::string& str, unsigned char xor_key)
{
const auto length = str.length();
file.write(reinterpret_cast<const char*>(&length), sizeof(length));
const auto check_sum = CheckSum(str);
file.write(reinterpret_cast<const char*>(&check_sum), sizeof(check_sum));
char buffer[length];
std::transform(str.c_str(), str.c_str() + length, buffer, [xor_key](char c){ return (c ^ xor_key); });
file.write(buffer, length);
}
void ReadString(std::ifstream& file, std::string& str, unsigned char xor_key)
{
std::size_t length;
file.read(reinterpret_cast<char*>(&length), sizeof(length));
unsigned char check_sum;
file.read(reinterpret_cast<char*>(&check_sum), sizeof(check_sum));
char buffer[length];
file.read(buffer, length);
std::transform(buffer, buffer + length, buffer, [xor_key](char c){ return (c ^ xor_key); });
str.assign(buffer, buffer + length);
if (check_sum != CheckSum(str))
{
throw MyException();
}
}
class User
{
User();
~User();
void Save() const;
void Load();
private:
static const unsigned char sm_name_key = 0x13;
static const unsigned char sm_password_key = 0x57;
private:
std::string m_file_name;
std::string m_name;
std::string m_password;
};
void User::Save() const
{
std: :o fstream file(m_file_name.c_str(), std::ios_base::binary);
::WriteString(file, m_name, sm_name_key);
::WriteString(file, m_password, sm_password_key);
}
void User::Load()
{
std::ifstream file(m_file_name.c_str(), std::ios_base::binary);
::ReadString(file, m_name, sm_name_key);
::ReadString(file, m_password, sm_password_key);
}
Предлагаю писать все данные просто в бинарный поток через write. Каждое поле записывать по правилу: сначала длина, потом чек-сумма, потом шифрованные данные. Поднимаем из файла в таком же порядке.
Небольшие наброски кода. Код писался в блокноте, так что могут быть опечатки.
[code]
#include <string>
#include <fstream>
#include <numeric>
#include <algorithm>
#include <functional>
inline unsigned char CheckSum(const std::string& str)
{
const auto sum = std::accumulate(str.cbegin(), str.cend(), 0ul);
// Оставляем только младший байт от всей суммы.
return static_cast<unsigned char>(sum);
}
void WriteString(std: :o fstream& file, const std::string& str, unsigned char xor_key)
{
const auto length = str.length();
file.write(reinterpret_cast<const char*>(&length), sizeof(length));
const auto check_sum = CheckSum(str);
file.write(reinterpret_cast<const char*>(&check_sum), sizeof(check_sum));
char buffer[length];
std::transform(str.c_str(), str.c_str() + length, buffer, [xor_key](char c){ return (c ^ xor_key); });
file.write(buffer, length);
}
void ReadString(std::ifstream& file, std::string& str, unsigned char xor_key)
{
std::size_t length;
file.read(reinterpret_cast<char*>(&length), sizeof(length));
unsigned char check_sum;
file.read(reinterpret_cast<char*>(&check_sum), sizeof(check_sum));
char buffer[length];
file.read(buffer, length);
std::transform(buffer, buffer + length, buffer, [xor_key](char c){ return (c ^ xor_key); });
str.assign(buffer, buffer + length);
if (check_sum != CheckSum(str))
{
throw MyException();
}
}
class User
{
User();
~User();
void Save() const;
void Load();
private:
static const unsigned char sm_name_key = 0x13;
static const unsigned char sm_password_key = 0x57;
private:
std::string m_file_name;
std::string m_name;
std::string m_password;
};
void User::Save() const
{
std: :o fstream file(m_file_name.c_str(), std::ios_base::binary);
::WriteString(file, m_name, sm_name_key);
::WriteString(file, m_password, sm_password_key);
}
void User::Load()
{
std::ifstream file(m_file_name.c_str(), std::ios_base::binary);
::ReadString(file, m_name, sm_name_key);
::ReadString(file, m_password, sm_password_key);
}
[/code]