如何只使用boost来将string编码为base64?

我试图快速编码一个简单的ASCIIstringbase64(使用boost :: asio的基本HTTP身份validation),而不是粘贴在任何新的代码或使用超出推广任何库。

简单的签名看起来像: string Base64Encode(const string&text);

我再次意识到algorithm很简单,有很多库/例子,但我正在寻找一个干净的例子。 我发现序列化提升,但没有明确的例子,或从谷歌。 http://www.boost.org/doc/libs/1_46_1/libs/serialization/doc/dataflow.html

这可能没有明确添加实际base64algorithm到我的代码?

我在你提供的链接中改进了这个例子:

#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> 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(); } 

这将打印string编码base64很好地形成一个换行符,每72个字符到控制台,准备被放入一个电子邮件。 如果你不喜欢换行,那就留在这里:

  typedef base64_from_binary< transform_width< const char *, 6, 8 > > base64_text; 

这是我的解决scheme。 它使用了与本页其他解决scheme相同的基本技巧,但解决了我觉得填充问题是一个更优雅的方式。 这个解决scheme也使用C ++ 11。

我认为大部分代码是自我解释的。 编码函数中的math位计算我们需要添加的“=”字符的数量。 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, '='); } 

使用boost base64编码解码的另一个解决scheme:

 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(); } 

这里是testing用例:

  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的任何人,这里是我的base64编码/解码function基于提升。 它按照上面的DanDan的评论正确地处理填充。 解码函数在遇到非法字符时会停止,并返回一个指向该字符的指针,如果您正在使用json或xmlparsingbase64,那么这是非常棒的。

 /// /// 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 。 我还没有find一个解决scheme。

我修改了答案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; } } 

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(); }