简单的签名如下: string Base64Encode(const string& text); 再次强调,我知道算法很简单,有许多库/示例可以完成此操作,但我正在寻找一个干净的boost示例。我发现了boost序列化,但那里没有清晰的示例或来自Google的示例。 http://www.boost.org/doc/libs/1_46_1/libs/serialization/doc/dataflow.html 是否可以在不将实际的base64算法明确添加到我的代码中的情况下实现这一点?
这是我的解决方案。它使用了与本页面上其他解决方案相同的基本技术,但以我认为更加优雅的方式解决了填充问题。此解决方案还利用了C ++11。
我认为大部分代码都是自说明的。编码函数中的数学位计算 '=' 字符的数量。val.size() 取模3的余数,但我们真正想要的是将 val.size() 减去下一个可被三整除的数字。由于我们有了余数,所以我们只需从3中减去余数,但如果我们想要0,则会留下3,因此我们还需要再取模3一次。
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <boost/algorithm/string.hpp>
std::string decode64(const std::string &val) {
using namespace boost::archive::iterators;
using It = transform_width<binary_from_base64<std::string::const_iterator>, 8, 6>;
return boost::algorithm::trim_right_copy_if(std::string(It(std::begin(val)), It(std::end(val))), [](char c) {
return c == '\0';
});
}
std::string encode64(const std::string &val) {
using namespace boost::archive::iterators;
using It = base64_from_binary<transform_width<std::string::const_iterator, 6, 8>>;
auto tmp = std::string(It(std::begin(val)), It(std::end(val)));
return tmp.append((3 - val.size() % 3) % 3, '=');
}
using
的方式! - Uli KöhlerIt
会导致编译错误,您可以将其更改为:
typedef transform_width<binary_from_base64<std::string::const_iterator>, 8, 6> It;
- g.d.d.c我稍微改进了你提供链接中的示例:
#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/insert_linebreaks.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <boost/archive/iterators/ostream_iterator.hpp>
#include <sstream>
#include <string>
#include <iostream>
int main()
{
using namespace boost::archive::iterators;
std::string test = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce ornare ullamcorper ipsum ac gravida.";
std::stringstream os;
typedef
insert_linebreaks< // insert line breaks every 72 characters
base64_from_binary< // convert binary values to base64 characters
transform_width< // retrieve 6 bit integers from a sequence of 8 bit bytes
const char *,
6,
8
>
>
,72
>
base64_text; // compose all the above operations in to a new iterator
std::copy(
base64_text(test.c_str()),
base64_text(test.c_str() + test.size()),
ostream_iterator<char>(os)
);
std::cout << os.str();
}
这将以base64编码格式漂亮地格式化字符串,并在每72个字符处添加换行符,准备输出到控制台以便放入电子邮件中。如果您不喜欢换行符,请使用以下代码:
typedef
base64_from_binary<
transform_width<
const char *,
6,
8
>
>
base64_text;
您可以使用Beast的实现。
对于Boost版本1.71,函数如下:
boost::beast::detail::base64::encode()
boost::beast::detail::base64::encoded_size()
boost::beast::detail::base64::decode()
boost::beast::detail::base64::decoded_size()
从#include <boost/beast/core/detail/base64.hpp>导入。
对于版本较旧的库,包括在1.66中的函数为:
boost::beast::detail::base64_encode()
boost::beast::detail::base64_decode()
来自#include <boost/beast/core/detail/base64.hpp>的内容。
boost::beast::detail::base64::encode()
。 - alkalinity另一个使用Boost Base64编码解码的解决方案:
const std::string base64_padding[] = {"", "==","="};
std::string base64_encode(const std::string& s) {
namespace bai = boost::archive::iterators;
std::stringstream os;
// convert binary values to base64 characters
typedef bai::base64_from_binary
// retrieve 6 bit integers from a sequence of 8 bit bytes
<bai::transform_width<const char *, 6, 8> > base64_enc; // compose all the above operations in to a new iterator
std::copy(base64_enc(s.c_str()), base64_enc(s.c_str() + s.size()),
std::ostream_iterator<char>(os));
os << base64_padding[s.size() % 3];
return os.str();
}
std::string base64_decode(const std::string& s) {
namespace bai = boost::archive::iterators;
std::stringstream os;
typedef bai::transform_width<bai::binary_from_base64<const char *>, 8, 6> base64_dec;
unsigned int size = s.size();
// Remove the padding characters, cf. https://svn.boost.org/trac/boost/ticket/5629
if (size && s[size - 1] == '=') {
--size;
if (size && s[size - 1] == '=') --size;
}
if (size == 0) return std::string();
std::copy(base64_dec(s.data()), base64_dec(s.data() + size),
std::ostream_iterator<char>(os));
return os.str();
}
以下是测试用例:
std::string t_e[TESTSET_SIZE] = {
""
, "M"
, "Ma"
, "Man"
, "pleasure."
, "leasure."
, "easure."
, "asure."
, "sure."
};
std::string t_d[TESTSET_SIZE] = {
""
, "TQ=="
, "TWE="
, "TWFu"
, "cGxlYXN1cmUu"
, "bGVhc3VyZS4="
, "ZWFzdXJlLg=="
, "YXN1cmUu"
, "c3VyZS4="
};
希望这可以帮助到您。对于从Google来到这里的任何人,以下是我基于boost开发的base64编码/解码函数。它可以正确处理填充,如DanDan在上面的评论中所说。解码函数在遇到非法字符时停止,并返回指向该字符的指针,如果您正在解析json或xml中的base64,则非常有用。
///
/// Convert up to len bytes of binary data in src to base64 and store it in dest
///
/// \param dest Destination buffer to hold the base64 data.
/// \param src Source binary data.
/// \param len The number of bytes of src to convert.
///
/// \return The number of characters written to dest.
/// \remarks Does not store a terminating null in dest.
///
uint base64_encode(char* dest, const char* src, uint len)
{
char tail[3] = {0,0,0};
typedef base64_from_binary<transform_width<const char *, 6, 8> > base64_enc;
uint one_third_len = len/3;
uint len_rounded_down = one_third_len*3;
uint j = len_rounded_down + one_third_len;
std::copy(base64_enc(src), base64_enc(src + len_rounded_down), dest);
if (len_rounded_down != len)
{
uint i=0;
for(; i < len - len_rounded_down; ++i)
{
tail[i] = src[len_rounded_down+i];
}
std::copy(base64_enc(tail), base64_enc(tail + 3), dest + j);
for(i=len + one_third_len + 1; i < j+4; ++i)
{
dest[i] = '=';
}
return i;
}
return j;
}
///
/// Convert null-terminated string src from base64 to binary and store it in dest.
///
/// \param dest Destination buffer
/// \param src Source base64 string
/// \param len Pointer to unsigned int representing size of dest buffer. After function returns this is set to the number of character written to dest.
///
/// \return Pointer to first character in source that could not be converted (the terminating null on success)
///
const char* base64_decode(char* dest, const char* src, uint* len)
{
uint output_len = *len;
typedef transform_width<binary_from_base64<const char*>, 8, 6> base64_dec;
uint i=0;
try
{
base64_dec src_it(src);
for(; i < output_len; ++i)
{
*dest++ = *src_it;
++src_it;
}
}
catch(dataflow_exception&)
{
}
*len = i;
return src + (i+2)/3*4; // bytes in = bytes out / 3 rounded up * 4
}
虽然编码工作正常,但解码器肯定是有问题的。此外,还有一个错误被打开:https://svn.boost.org/trac/boost/ticket/5629。我还没有找到解决方法。
这是另一个答案:
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/transform_width.hpp>
std::string ToBase64(const std::vector<unsigned char>& binary)
{
using namespace boost::archive::iterators;
using It = base64_from_binary<transform_width<std::vector<unsigned char>::const_iterator, 6, 8>>;
auto base64 = std::string(It(binary.begin()), It(binary.end()));
// Add padding.
return base64.append((3 - binary.size() % 3) % 3, '=');
}
std::vector<unsigned char> FromBase64(const std::string& base64)
{
using namespace boost::archive::iterators;
using It = transform_width<binary_from_base64<std::string::const_iterator>, 8, 6>;
auto binary = std::vector<unsigned char>(It(base64.begin()), It(base64.end()));
// Remove padding.
auto length = base64.size();
if(binary.size() > 2 && base64[length - 1] == '=' && base64[length - 2] == '=')
{
binary.erase(binary.end() - 2, binary.end());
}
else if(binary.size() > 1 && base64[length - 1] == '=')
{
binary.erase(binary.end() - 1, binary.end());
}
return binary;
}
将文本和数据进行Base64编码
const std::string base64_padding[] = {"", "==","="};
std::string base64EncodeText(std::string text) {
using namespace boost::archive::iterators;
typedef std::string::const_iterator iterator_type;
typedef base64_from_binary<transform_width<iterator_type, 6, 8> > base64_enc;
std::stringstream ss;
std::copy(base64_enc(text.begin()), base64_enc(text.end()), ostream_iterator<char>(ss));
ss << base64_padding[text.size() % 3];
return ss.str();
}
std::string base64EncodeData(std::vector<uint8_t> data) {
using namespace boost::archive::iterators;
typedef std::vector<uint8_t>::const_iterator iterator_type;
typedef base64_from_binary<transform_width<iterator_type, 6, 8> > base64_enc;
std::stringstream ss;
std::copy(base64_enc(data.begin()), base64_enc(data.end()), ostream_iterator<char>(ss));
ss << base64_padding[data.size() % 3];
return ss.str();
}
我修改了答案8,因为它在我的平台上无法正常运行。
const std::string base64_padding[] = {"", "==","="};
std::string *m_ArchiveData;
/// \brief To Base64 string
bool Base64Encode(string* output)
{
try
{
UInt32 iPadding_Mask = 0;
typedef boost::archive::iterators::base64_from_binary
<boost::archive::iterators::transform_width<const char *, 6, 8> > Base64EncodeIterator;
UInt32 len = m_ArchiveData->size();
std::stringstream os;
std::copy(Base64EncodeIterator(m_ArchiveData->c_str()),
Base64EncodeIterator(m_ArchiveData->c_str()+len),
std::ostream_iterator<char>(os));
iPadding_Mask = m_ArchiveData->size() % 3;
os << base64_padding[iPadding_Pask];
*output = os.str();
return output->empty() == false;
}
catch (...)
{
PLOG_ERROR_DEV("unknown error happens");
return false;
}
}
/// \brief From Base64 string
bool mcsf_data_header_byte_stream_archive::Base64Decode(const std::string *input)
{
try
{
std::stringstream os;
bool bPaded = false;
typedef boost::archive::iterators::transform_width<boost::archive::iterators::
binary_from_base64<const char *>, 8, 6> Base64DecodeIterator;
UInt32 iLength = input->length();
// Remove the padding characters, cf. https://svn.boost.org/trac/boost/ticket/5629
if (iLength && (*input)[iLength-1] == '=') {
bPaded = true;
--iLength;
if (iLength && (*input)[iLength - 1] == '=')
{
--iLength;
}
}
if (iLength == 0)
{
return false;
}
if(bPaded)
{
iLength --;
}
copy(Base64DecodeIterator(input->c_str()) ,
Base64DecodeIterator(input->c_str()+iLength),
ostream_iterator<char>(os));
*m_ArchiveData = os.str();
return m_ArchiveData->empty() == false;
}
catch (...)
{
PLOG_ERROR_DEV("unknown error happens");
return false;
}
}