任何人都有c ++中免费提供的base64解码代码片段?
这是我对RenéNyffenegger最初编写的实现的修改.为什么我要修改它?好吧,因为我觉得我应该使用存储在对象中的二进制数据;)std::string
base64.h:
#ifndef _BASE64_H_ #define _BASE64_H_ #include#include typedef unsigned char BYTE; std::string base64_encode(BYTE const* buf, unsigned int bufLen); std::vector base64_decode(std::string const&); #endif
base64.cpp:
#include "base64.h" #includestatic const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; static inline bool is_base64(BYTE c) { return (isalnum(c) || (c == '+') || (c == '/')); } std::string base64_encode(BYTE const* buf, unsigned int bufLen) { std::string ret; int i = 0; int j = 0; BYTE char_array_3[3]; BYTE char_array_4[4]; while (bufLen--) { char_array_3[i++] = *(buf++); if (i == 3) { char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); char_array_4[3] = char_array_3[2] & 0x3f; for(i = 0; (i <4) ; i++) ret += base64_chars[char_array_4[i]]; i = 0; } } if (i) { for(j = i; j < 3; j++) char_array_3[j] = '\0'; char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); char_array_4[3] = char_array_3[2] & 0x3f; for (j = 0; (j < i + 1); j++) ret += base64_chars[char_array_4[j]]; while((i++ < 3)) ret += '='; } return ret; } std::vector base64_decode(std::string const& encoded_string) { int in_len = encoded_string.size(); int i = 0; int j = 0; int in_ = 0; BYTE char_array_4[4], char_array_3[3]; std::vector ret; while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { char_array_4[i++] = encoded_string[in_]; in_++; if (i ==4) { for (i = 0; i <4; i++) char_array_4[i] = base64_chars.find(char_array_4[i]); char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; for (i = 0; (i < 3); i++) ret.push_back(char_array_3[i]); i = 0; } } if (i) { for (j = i; j <4; j++) char_array_4[j] = 0; for (j = 0; j <4; j++) char_array_4[j] = base64_chars.find(char_array_4[j]); char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; for (j = 0; (j < i - 1); j++) ret.push_back(char_array_3[j]); } return ret; }
这是用法:
std::vectormyData; ... std::string encodedData = base64_encode(&myData[0], myData.size()); std::vector decodedData = base64_decode(encodedData);
我希望有人会发现这个答案有用^^
谷歌是你的朋友
以下是该页面的实现:
/* base64.cpp and base64.h Copyright (C) 2004-2008 René Nyffenegger This source code is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this source code must not be misrepresented; you must not claim that you wrote the original source code. If you use this source code in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original source code. 3. This notice may not be removed or altered from any source distribution. René Nyffenegger rene.nyffenegger@adp-gmbh.ch */ static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; static inline bool is_base64(unsigned char c) { return (isalnum(c) || (c == '+') || (c == '/')); } std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) { std::string ret; int i = 0; int j = 0; unsigned char char_array_3[3]; unsigned char char_array_4[4]; while (in_len--) { char_array_3[i++] = *(bytes_to_encode++); if (i == 3) { char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); char_array_4[3] = char_array_3[2] & 0x3f; for(i = 0; (i <4) ; i++) ret += base64_chars[char_array_4[i]]; i = 0; } } if (i) { for(j = i; j < 3; j++) char_array_3[j] = '\0'; char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); char_array_4[3] = char_array_3[2] & 0x3f; for (j = 0; (j < i + 1); j++) ret += base64_chars[char_array_4[j]]; while((i++ < 3)) ret += '='; } return ret; } std::string base64_decode(std::string const& encoded_string) { int in_len = encoded_string.size(); int i = 0; int j = 0; int in_ = 0; unsigned char char_array_4[4], char_array_3[3]; std::string ret; while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { char_array_4[i++] = encoded_string[in_]; in_++; if (i ==4) { for (i = 0; i <4; i++) char_array_4[i] = base64_chars.find(char_array_4[i]); char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; for (i = 0; (i < 3); i++) ret += char_array_3[i]; i = 0; } } if (i) { for (j = i; j <4; j++) char_array_4[j] = 0; for (j = 0; j <4; j++) char_array_4[j] = base64_chars.find(char_array_4[j]); char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; } return ret; }
这里有几个片段.然而,这个是紧凑,高效,和c ++ 11友好:
static std::string base64_encode(const std::string &in) { std::string out; int val=0, valb=-6; for (uchar c : in) { val = (val<<8) + c; valb += 8; while (valb>=0) { out.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(val>>valb)&0x3F]); valb-=6; } } if (valb>-6) out.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[((val<<8)>>(valb+8))&0x3F]); while (out.size()%4) out.push_back('='); return out; } static std::string base64_decode(const std::string &in) { std::string out; std::vectorT(256,-1); for (int i=0; i<64; i++) T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i; int val=0, valb=-8; for (uchar c : in) { if (T[c] == -1) break; val = (val<<6) + T[c]; valb += 6; if (valb>=0) { out.push_back(char((val>>valb)&0xFF)); valb-=8; } } return out; }
使用base-n mini lib,您可以执行以下操作:
some_data_t in[] { ... }; constexpr int len = sizeof(in)/sizeof(in[0]); std::string encoded; bn::encode_b64(in, in + len, std::back_inserter(encoded)); some_data_t out[len]; bn::decode_b64(encoded.begin(), encoded.end(), out);
API是通用的,基于迭代器的.
披露:我是作者.
我认为这个更好用:
#includestatic const char* B64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const int B64index[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 63, 62, 62, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 63, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 }; const std::string b64encode(const void* data, const size_t &len) { std::string result((len + 2) / 3 * 4, '='); char *p = (char*) data, *str = &result[0]; size_t j = 0, pad = len % 3; const size_t last = len - pad; for (size_t i = 0; i < last; i += 3) { int n = int(p[i]) << 16 | int(p[i + 1]) << 8 | p[i + 2]; str[j++] = B64chars[n >> 18]; str[j++] = B64chars[n >> 12 & 0x3F]; str[j++] = B64chars[n >> 6 & 0x3F]; str[j++] = B64chars[n & 0x3F]; } if (pad) /// set padding { int n = --pad ? int(p[last]) << 8 | p[last + 1] : p[last]; str[j++] = B64chars[pad ? n >> 10 & 0x3F : n >> 2]; str[j++] = B64chars[pad ? n >> 4 & 0x03F : n << 4 & 0x3F]; str[j++] = pad ? B64chars[n << 2 & 0x3F] : '='; } return result; } const std::string b64decode(const void* data, const size_t &len) { if (len == 0) return ""; unsigned char *p = (unsigned char*) data; size_t j = 0, pad1 = len % 4 || p[len - 1] == '=', pad2 = pad1 && (len % 4 > 2 || p[len - 2] != '='); const size_t last = (len - pad1) / 4 << 2; std::string result(last / 4 * 3 + pad1 + pad2, '\0'); unsigned char *str = (unsigned char*) &result[0]; for (size_t i = 0; i < last; i += 4) { int n = B64index[p[i]] << 18 | B64index[p[i + 1]] << 12 | B64index[p[i + 2]] << 6 | B64index[p[i + 3]]; str[j++] = n >> 16; str[j++] = n >> 8 & 0xFF; str[j++] = n & 0xFF; } if (pad1) { int n = B64index[p[last]] << 18 | B64index[p[last + 1]] << 12; str[j++] = n >> 16; if (pad2) { n |= B64index[p[last + 2]] << 6; str[j++] = n >> 8 & 0xFF; } } return result; } std::string b64encode(const std::string& str) { return b64encode(str.c_str(), str.size()); } std::string b64decode(const std::string& str64) { return b64decode(str64.c_str(), str64.size()); }
感谢@Jens Alfke指出性能问题,我对这篇旧帖子进行了一些修改.这个比以前更快.它的另一个优点是可以顺利处理损坏的数据.
上一版:虽然在这些类型的问题中,似乎速度是一种矫枉过正,但仅仅为了它的乐趣,我做了一些其他修改,使其成为AFAIK中最快的算法.特别感谢@GaspardP的宝贵建议和不错的基准.
根据GaspardP的这一优秀比较,我不会选择这个解决方案.这不是最糟糕的,但它也不是最好的.它唯一能做的就是它可能更容易理解.
我发现另外两个答案很难理解.它们还会在我的编译器中产生一些警告,并且在解码部分中使用find函数会导致效率非常差.所以我决定推出自己的.
标题:
#ifndef _BASE64_H_ #define _BASE64_H_ #include#include typedef unsigned char BYTE; class Base64 { public: static std::string encode(const std::vector & buf); static std::string encode(const BYTE* buf, unsigned int bufLen); static std::vector decode(std::string encoded_string); }; #endif
身体:
static const BYTE from_base64[] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 62, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 63, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255}; static const char to_base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; std::string Base64::encode(const std::vector& buf) { if (buf.empty()) return ""; // Avoid dereferencing buf if it's empty return encode(&buf[0], (unsigned int)buf.size()); } std::string Base64::encode(const BYTE* buf, unsigned int bufLen) { // Calculate how many bytes that needs to be added to get a multiple of 3 size_t missing = 0; size_t ret_size = bufLen; while ((ret_size % 3) != 0) { ++ret_size; ++missing; } // Expand the return string size to a multiple of 4 ret_size = 4*ret_size/3; std::string ret; ret.reserve(ret_size); for (unsigned int i=0; i > 2); b4[1] = ((b3[0] & 0x03) << 4) + ((b3[1] & 0xf0) >> 4); b4[2] = ((b3[1] & 0x0f) << 2) + ((b3[2] & 0xc0) >> 6); b4[3] = ((b3[2] & 0x3f) << 0); // Add the base 64 characters to the return value ret.push_back(to_base64[b4[0]]); ret.push_back(to_base64[b4[1]]); ret.push_back(to_base64[b4[2]]); ret.push_back(to_base64[b4[3]]); } // Replace data that is invalid (always as many as there are missing bytes) for (size_t i=0; i Base64::decode(std::string encoded_string) { // Make sure string length is a multiple of 4 while ((encoded_string.size() % 4) != 0) encoded_string.push_back('='); size_t encoded_size = encoded_string.size(); std::vector ret; ret.reserve(3*encoded_size/4); for (size_t i=0; i > 4); b3[1] = ((b4[1] & 0x0f) << 4) + ((b4[2] & 0x3c) >> 2); b3[2] = ((b4[2] & 0x03) << 6) + ((b4[3] & 0x3f) >> 0); // Add the byte to the return value if it isn't part of an '=' character (indicated by 0xff) if (b4[1] != 0xff) ret.push_back(b3[0]); if (b4[2] != 0xff) ret.push_back(b3[1]); if (b4[3] != 0xff) ret.push_back(b3[2]); } return ret; }
用法:
BYTE buf[] = "ABCD"; std::string encoded = Base64::encode(buf, 4); // encoded = "QUJDRA==" std::vectordecoded = Base64::decode(encoded);
这里的一个好处是解码功能还可以解码base 64编码的url变体.