这是我第四次尝试进行 base64 编码。我的第一次尝试工作,但它不是标准的。也特别慢!!!我使用了 vector 和 push_back 并删除了很多内容。
所以我决定重写它,这样速度快多了!除了它丢失数据。 -__- 我需要尽可能快的速度,因为我正在压缩像素缓冲区和 base64 编码压缩字符串。我正在使用 ZLib。图片是 1366 x 768,是的。
我不想复制我在网上找到的任何代码,因为......好吧,我喜欢自己写东西,我不喜欢担心版权问题或者不得不在我的整个过程中从不同的来源获得大量的学分代码..
无论如何,我的代码如下。它非常简短。
const static std::string Base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
inline bool IsBase64(std::uint8_t C)
{
return (isalnum(C) || (C == '+') || (C == '/'));
}
std::string Copy(std::string Str, int FirstChar, int Count)
{
if (FirstChar <= 0)
FirstChar = 0;
else
FirstChar -= 1;
return Str.substr(FirstChar, Count);
}
std::string DecToBinStr(int Num, int Padding)
{
int Bin = 0, Pos = 1;
std::stringstream SS;
while (Num > 0)
{
Bin += (Num % 2) * Pos;
Num /= 2;
Pos *= 10;
}
SS.fill('0');
SS.width(Padding);
SS << Bin;
return SS.str();
}
int DecToBinStr(std::string DecNumber)
{
int Bin = 0, Pos = 1;
int Dec = strtol(DecNumber.c_str(), NULL, 10);
while (Dec > 0)
{
Bin += (Dec % 2) * Pos;
Dec /= 2;
Pos *= 10;
}
return Bin;
}
int BinToDecStr(std::string BinNumber)
{
int Dec = 0;
int Bin = strtol(BinNumber.c_str(), NULL, 10);
for (int I = 0; Bin > 0; ++I)
{
if(Bin % 10 == 1)
{
Dec += (1 << I);
}
Bin /= 10;
}
return Dec;
}
std::string EncodeBase64(std::string Data)
{
std::string Binary = std::string();
std::string Result = std::string();
for (std::size_t I = 0; I < Data.size(); ++I)
{
Binary += DecToBinStr(Data[I], 8);
}
for (std::size_t I = 0; I < Binary.size(); I += 6)
{
Result += Base64Chars[BinToDecStr(Copy(Binary, I, 6))];
if (I == 0) ++I;
}
int PaddingAmount = ((-Result.size() * 3) & 3);
for (int I = 0; I < PaddingAmount; ++I)
Result += '=';
return Result;
}
std::string DecodeBase64(std::string Data)
{
std::string Binary = std::string();
std::string Result = std::string();
for (std::size_t I = Data.size(); I > 0; --I)
{
if (Data[I - 1] != '=')
{
std::string Characters = Copy(Data, 0, I);
for (std::size_t J = 0; J < Characters.size(); ++J)
Binary += DecToBinStr(Base64Chars.find(Characters[J]), 6);
break;
}
}
for (std::size_t I = 0; I < Binary.size(); I += 8)
{
Result += (char)BinToDecStr(Copy(Binary, I, 8));
if (I == 0) ++I;
}
return Result;
}
我一直在像这样使用上面的内容:
int main()
{
std::string Data = EncodeBase64("IMG." + ::ToString(677) + "*" + ::ToString(604)); //IMG.677*604
std::cout<<DecodeBase64(Data); //Prints IMG.677*601
}
正如您在上面看到的,它打印了错误的字符串。它相当接近,但由于某种原因,4 变成了 1!
现在如果我这样做:
int main()
{
std::string Data = EncodeBase64("IMG." + ::ToString(1366) + "*" + ::ToString(768)); //IMG.1366*768
std::cout<<DecodeBase64(Data); //Prints IMG.1366*768
}
它打印正确。我完全不确定发生了什么或从哪里开始寻找。
以防万一有人好奇并想看看我的其他尝试(慢的):http://pastebin.com/Xcv03KwE
我真的希望有人能阐明一些加快速度的方法,或者至少找出我的代码有什么问题 :l
最佳答案
主要的编码问题是您没有考虑不是 6 位倍数的数据。在这种情况下,您拥有的最终 4
被转换为 0100
而不是 010000
因为没有更多的位可以读取。您应该使用 0
进行填充。
像这样更改Copy
后,最终编码的字符是Q
,而不是原来的E
。
std::string data = Str.substr(FirstChar, Count);
while(data.size() < Count) data += '0';
return data;
此外,您添加填充 =
的逻辑似乎已关闭,因为在这种情况下它添加了太多 =
。
就速度方面的评论而言,我主要关注的是尽量减少对 std::string
的使用。考虑到可以使用按位运算符直接读取源,您当前将数据转换为包含 0 和 1 的字符串的方式非常低效。
关于c++ - Base 64 编码丢失数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14097360/