如何在 C++ 中将 Base64 字符串转换为十六进制字符串?

发布于 2024-10-11 23:48:57 字数 794 浏览 2 评论 0原文

我有一个表示 base64 值的字符串。我想将此字符串从 base64 转换为十六进制。我在 Ubuntu 10.10 上使用 C++ 工作。我有以下代码:

std::string ssir = "DNQwSinfOUSSWd+U04r23A==";
std::string dec=(base64_decode(ssir));
std::stringstream ss;

for (int i=0; i<dec.size(); ++i) {
    if (i != 0) ss << ':';
 ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned int>(dec[i]);//(int)(dec[i]);
}
std::string res;
res= ss.str();
cout<<"the ress is: "<<res<<std::endl;

结果是:

0c:ffffffd4:30:4a:29:ffffffdf:39:44:ffffff92:59:ffffffdf:ffffff94:ffffffd3:ffffff8a:ffffffff6:ffffffdc

除了那些ffffffff之外,它是正确的。我可以做什么来解决这个问题?如果我希望将十六进制结果写入 std::vector; x,我该怎么办?

I have a string that represents a value in base64. I want to convert this string from base64 to hexadecimal. I'm working in C++ on Ubuntu 10.10. I have the following code:

std::string ssir = "DNQwSinfOUSSWd+U04r23A==";
std::string dec=(base64_decode(ssir));
std::stringstream ss;

for (int i=0; i<dec.size(); ++i) {
    if (i != 0) ss << ':';
 ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned int>(dec[i]);//(int)(dec[i]);
}
std::string res;
res= ss.str();
cout<<"the ress is: "<<res<<std::endl;

The result is:

0c:ffffffd4:30:4a:29:ffffffdf:39:44:ffffff92:59:ffffffdf:ffffff94:ffffffd3:ffffff8a:fffffff6:ffffffdc

It is correct, besides those ffffffff. What can I do to fix this? If I want my hexadecimal result to be written to a std::vector<unsigned char> x, what do I have to do?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

飘过的浮云 2024-10-18 23:48:58

尝试使用此转换:

static_cast<unsigned char>(dec[i])

int 是 32 位宽,而您只想输出 8 位,这就是 char 的宽度。大概 std::hex 在格式化数字时考虑输入类型。 (虽然我不太确定符号扩展来自哪里,因为您正在转换为无符号类型......)

Try using this cast instead:

static_cast<unsigned char>(dec[i])

int is 32 bits wide and you only want to output 8 bits, which is how wide char is. Presumably std::hex is considering the input type when formatting the number. (Though I'm not quite sure where the sign extension is coming from, since you are casting to an unsigned type...)

度的依靠╰つ 2024-10-18 23:48:58

您可以尝试另一种字符串到十六进制转换方法。我写了两个函数。 str_to_hex - 是我的方法。 str_to_hex2 - 是你的。我省略了base64编码。然后我调用了我的函数和你的函数 1M 次。 str_to_hex 的执行时间为

time ./a.out 

real    0m0.365s
user    0m0.360s
sys 0m0.010s

str_to_hex2 的执行时间为:

time ./a.out 

real    0m3.253s
user    0m3.220s
sys 0m0.000s

Ubuntu 10.04,64位,g++ 4.4.3,-O3选项。

测试程序代码如下。

#include <string>
#include <iostream>
#include <sstream>
#include <iomanip>

void str_to_hex() {
    std::string ssir = "DNQwSinfOUSSWd+U04r23A==";
    static const char *hex = "0123456789ABCDEF";
    std::string result;
    result.reserve(ssir.size() * 3);
    for (std::string::const_iterator i = ssir.begin(), end = ssir.end(); i != end; ++i) {
        if (i != ssir.begin())
            result.push_back(':');
        result.push_back(hex[*i >> 4]);
        result.push_back(hex[*i & 0xf]);
    }
}

void str_to_hex2() {
    std::string ssir = "DNQwSinfOUSSWd+U04r23A==";
    std::stringstream ss;
    for (int i=0; i<ssir.size(); ++i) {
            if (i != 0) ss << ':';
             ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned int>(ssir[i] & 0xff);
    }
}

int main() {
    for (int i = 0; i < 1000000; ++i)
        str_to_hex();

}

You can try another string to hex conversion method. I wrote two functions. The str_to_hex - is my method. str_to_hex2 - is your. I omit base64 encoding. And then I invoked 1M times my function and your. The execution time for str_to_hex is

time ./a.out 

real    0m0.365s
user    0m0.360s
sys 0m0.010s

And the execution time for str_to_hex2 is:

time ./a.out 

real    0m3.253s
user    0m3.220s
sys 0m0.000s

Ubuntu 10.04, 64bit, g++ 4.4.3, -O3 option.

The code of testing programm is below.

#include <string>
#include <iostream>
#include <sstream>
#include <iomanip>

void str_to_hex() {
    std::string ssir = "DNQwSinfOUSSWd+U04r23A==";
    static const char *hex = "0123456789ABCDEF";
    std::string result;
    result.reserve(ssir.size() * 3);
    for (std::string::const_iterator i = ssir.begin(), end = ssir.end(); i != end; ++i) {
        if (i != ssir.begin())
            result.push_back(':');
        result.push_back(hex[*i >> 4]);
        result.push_back(hex[*i & 0xf]);
    }
}

void str_to_hex2() {
    std::string ssir = "DNQwSinfOUSSWd+U04r23A==";
    std::stringstream ss;
    for (int i=0; i<ssir.size(); ++i) {
            if (i != 0) ss << ':';
             ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned int>(ssir[i] & 0xff);
    }
}

int main() {
    for (int i = 0; i < 1000000; ++i)
        str_to_hex();

}
漫雪独思 2024-10-18 23:48:58

我不确定这是否是最好的解决方案,但这就是我的做法。

#include <vector>
#include <bitset>
#include <string>

//hex->dec->bin8->bin6->dec->base64table

//HexToDec
unsigned int HexToDec(std::string hexInput)
{
    //initlize variables
    const int HexBaseASCCI = 48;
    const int HexBase = 16;
    size_t hexCharPlace = hexInput.size() -1;
    int  result  = 0;

    //reading the hexInput
    for (int i = 0; i < hexInput.size(); i++)
    {
        char hexChar = hexInput.at(i);
        int  dec  = 0;
        //Finde the equvilcey of the char hex u read from the HexNum string
        if (hexChar>='0' && hexChar<='9'){dec = (int)hexChar - HexBaseASCCI;}
        else
        { switch (hexChar)
            {   case ('A') :
                case ('a') : {dec = 10; break;}
                case ('B') :
                case ('b') : {dec = 11; break;}
                case ('C') :
                case ('c') : {dec = 12; break;}
                case ('D') :
                case ('d') : {dec = 13; break;}
                case ('E') :
                case ('e') : {dec = 14; break;}
                case ('F') :
                case ('f') : {dec = 15; break;}
                case ('X') :
                case ('x') : {dec = 0; break;}
                default    : {

                    std::string msg ("is not in hex format");
                    throw std::logic_error(msg);};
            }
        }

        //calculating the final dec
        result += dec * pow(HexBase,hexCharPlace);
        hexCharPlace--;
    }

    return result;
}

//HexToDec vector version
std::vector<unsigned int> HexToDec(std::vector<std::string> hex)
{

    std::vector<unsigned int> dec;

    for( auto x : hex){
        dec.push_back(HexToDec(x));
    }
    return dec;
}

//BreakHexStringIntoGroups           TODO .. needs to imporve
std::vector<std::string> BreakHexStringIntoGroups(std::string hexInput, unsigned long lengthOfBreaks)
{
    std::vector<std::string> hexGroups;

    if(!(hexInput.size() % 2)){

        for (auto index(0); index < hexInput.size(); index+=lengthOfBreaks )
        {
            hexGroups.push_back(hexInput.substr(index,lengthOfBreaks));

        }
    }
    else
    {
        for (auto index(0); index < hexInput.size()-1; index+=lengthOfBreaks )
        {
            hexGroups.push_back(hexInput.substr(index,lengthOfBreaks));

        }
        hexGroups.push_back(hexInput.substr(hexInput.size()-1));
    }
    return hexGroups;
}

//DecTo8BitsBin
std::vector<std::string> DecTo8BitsBin(std::vector<unsigned int> dec)
{
    std::vector<std::string> bin;
    for (auto x: dec)
    {
         bin.push_back(std::bitset<8>(x).to_string());
    }
    return bin;
}

//FuseStringVector
std::string FuseStringVector(std::vector<std::string> vec)
{
    std::string res;

    for (auto str: vec)
    {
        res+=str;
    }
    return res;
}

//BreakBinStringInto6BitsGroups      TODO .. needs to imporve
std::vector<std::string> BreakBinStringInto6BitsGroups(std::string longBin){

    std::vector<std::string> res;
    if (!(longBin.size() % 6))
    {
        for (unsigned int i(0) ; i < longBin.size(); i+=6){

            res.push_back(longBin.substr(i,6));
        }
    }
    else
    {
        unsigned int max6AlignedIndex = (longBin.size() / 6)*6;
        unsigned int paddingZeros = 6 -(longBin.size() % 6);

        for (unsigned int i(0) ; i < max6AlignedIndex; i+=6){

            res.push_back(longBin.substr(i,6));
        }
        res.push_back(longBin.substr(max6AlignedIndex) + std::string(paddingZeros, '0'));
    }

    return res;
}


//Bin6BitsToDec
unsigned int Bin6BitsToDec(std::string bin6Bit){

    unsigned int decimalNumber(0), i(0), remainder(0);
    unsigned int n (std::stoi(bin6Bit));

    while (n!=0)
    {
        remainder = n%10;
        n /= 10;
        decimalNumber += remainder*pow(2,i);
        ++i;
    }
    return decimalNumber;
}

//Bin6BitsToDec  vector
std::vector<unsigned int> Bin6BitsToDec(std::vector<std::string> bin6Bits)
{
    std::vector<unsigned int> dec;

    for(auto bin: bin6Bits)
    {
        dec.push_back(Bin6BitsToDec(bin));
    }
    return dec;
}


//DecToBase64
std::vector<char> DecToBase64(std::vector<unsigned int> dec)
{
    const std::string base64Table("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
    std::vector<char> res;

    for(auto x: dec)
    {
        res.push_back(base64Table.at(x));
    }
    return res;
}

//FuseCharVector
std::string FuseCharVector(std::vector<char> vec)
{
    return std::string(vec.begin(), vec.end());
}


std::string HexToBase64(std::string hex){

    std::vector<std::string> brokenHexGroups(BreakHexStringIntoGroups(hex,2));
    std::vector<unsigned int> brokenHexGroupsInDec(HexToDec(brokenHexGroups));
    std::vector<std::string> bin8bits= DecTo8BitsBin(brokenHexGroupsInDec);
    std::string fusedBin8bits = FuseStringVector(bin8bits);
    std::vector<std::string> bin6Bits = BreakBinStringInto6BitsGroups(fusedBin8bits);
    std::vector<unsigned int> bin6BitsInDec(Bin6BitsToDec(bin6Bits));
    std::vector<char> decToBase64Chars = DecToBase64(bin6BitsInDec);
    std::string finalString = FuseCharVector(decToBase64Chars);


    return finalString;
}

I am not sure if this is the best solution but this is how I did it.

#include <vector>
#include <bitset>
#include <string>

//hex->dec->bin8->bin6->dec->base64table

//HexToDec
unsigned int HexToDec(std::string hexInput)
{
    //initlize variables
    const int HexBaseASCCI = 48;
    const int HexBase = 16;
    size_t hexCharPlace = hexInput.size() -1;
    int  result  = 0;

    //reading the hexInput
    for (int i = 0; i < hexInput.size(); i++)
    {
        char hexChar = hexInput.at(i);
        int  dec  = 0;
        //Finde the equvilcey of the char hex u read from the HexNum string
        if (hexChar>='0' && hexChar<='9'){dec = (int)hexChar - HexBaseASCCI;}
        else
        { switch (hexChar)
            {   case ('A') :
                case ('a') : {dec = 10; break;}
                case ('B') :
                case ('b') : {dec = 11; break;}
                case ('C') :
                case ('c') : {dec = 12; break;}
                case ('D') :
                case ('d') : {dec = 13; break;}
                case ('E') :
                case ('e') : {dec = 14; break;}
                case ('F') :
                case ('f') : {dec = 15; break;}
                case ('X') :
                case ('x') : {dec = 0; break;}
                default    : {

                    std::string msg ("is not in hex format");
                    throw std::logic_error(msg);};
            }
        }

        //calculating the final dec
        result += dec * pow(HexBase,hexCharPlace);
        hexCharPlace--;
    }

    return result;
}

//HexToDec vector version
std::vector<unsigned int> HexToDec(std::vector<std::string> hex)
{

    std::vector<unsigned int> dec;

    for( auto x : hex){
        dec.push_back(HexToDec(x));
    }
    return dec;
}

//BreakHexStringIntoGroups           TODO .. needs to imporve
std::vector<std::string> BreakHexStringIntoGroups(std::string hexInput, unsigned long lengthOfBreaks)
{
    std::vector<std::string> hexGroups;

    if(!(hexInput.size() % 2)){

        for (auto index(0); index < hexInput.size(); index+=lengthOfBreaks )
        {
            hexGroups.push_back(hexInput.substr(index,lengthOfBreaks));

        }
    }
    else
    {
        for (auto index(0); index < hexInput.size()-1; index+=lengthOfBreaks )
        {
            hexGroups.push_back(hexInput.substr(index,lengthOfBreaks));

        }
        hexGroups.push_back(hexInput.substr(hexInput.size()-1));
    }
    return hexGroups;
}

//DecTo8BitsBin
std::vector<std::string> DecTo8BitsBin(std::vector<unsigned int> dec)
{
    std::vector<std::string> bin;
    for (auto x: dec)
    {
         bin.push_back(std::bitset<8>(x).to_string());
    }
    return bin;
}

//FuseStringVector
std::string FuseStringVector(std::vector<std::string> vec)
{
    std::string res;

    for (auto str: vec)
    {
        res+=str;
    }
    return res;
}

//BreakBinStringInto6BitsGroups      TODO .. needs to imporve
std::vector<std::string> BreakBinStringInto6BitsGroups(std::string longBin){

    std::vector<std::string> res;
    if (!(longBin.size() % 6))
    {
        for (unsigned int i(0) ; i < longBin.size(); i+=6){

            res.push_back(longBin.substr(i,6));
        }
    }
    else
    {
        unsigned int max6AlignedIndex = (longBin.size() / 6)*6;
        unsigned int paddingZeros = 6 -(longBin.size() % 6);

        for (unsigned int i(0) ; i < max6AlignedIndex; i+=6){

            res.push_back(longBin.substr(i,6));
        }
        res.push_back(longBin.substr(max6AlignedIndex) + std::string(paddingZeros, '0'));
    }

    return res;
}


//Bin6BitsToDec
unsigned int Bin6BitsToDec(std::string bin6Bit){

    unsigned int decimalNumber(0), i(0), remainder(0);
    unsigned int n (std::stoi(bin6Bit));

    while (n!=0)
    {
        remainder = n%10;
        n /= 10;
        decimalNumber += remainder*pow(2,i);
        ++i;
    }
    return decimalNumber;
}

//Bin6BitsToDec  vector
std::vector<unsigned int> Bin6BitsToDec(std::vector<std::string> bin6Bits)
{
    std::vector<unsigned int> dec;

    for(auto bin: bin6Bits)
    {
        dec.push_back(Bin6BitsToDec(bin));
    }
    return dec;
}


//DecToBase64
std::vector<char> DecToBase64(std::vector<unsigned int> dec)
{
    const std::string base64Table("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
    std::vector<char> res;

    for(auto x: dec)
    {
        res.push_back(base64Table.at(x));
    }
    return res;
}

//FuseCharVector
std::string FuseCharVector(std::vector<char> vec)
{
    return std::string(vec.begin(), vec.end());
}


std::string HexToBase64(std::string hex){

    std::vector<std::string> brokenHexGroups(BreakHexStringIntoGroups(hex,2));
    std::vector<unsigned int> brokenHexGroupsInDec(HexToDec(brokenHexGroups));
    std::vector<std::string> bin8bits= DecTo8BitsBin(brokenHexGroupsInDec);
    std::string fusedBin8bits = FuseStringVector(bin8bits);
    std::vector<std::string> bin6Bits = BreakBinStringInto6BitsGroups(fusedBin8bits);
    std::vector<unsigned int> bin6BitsInDec(Bin6BitsToDec(bin6Bits));
    std::vector<char> decToBase64Chars = DecToBase64(bin6BitsInDec);
    std::string finalString = FuseCharVector(decToBase64Chars);


    return finalString;
}
无声情话 2024-10-18 23:48:57

@cdhowie 的帖子几乎是正确的。但是,如果您转换为 char(有符号或无符号),标准流运算符将尝试写出该字符的 ASCII 值。您将需要另一个强制转换:

static_cast<int>(static_cast<unsigned char>(dec[i]))

或显式截断值:(

(static_cast<int>(dec[i]) & 0xFF)

在这两种情况下,外部 int 不需要是 unsigned;在第一种情况下,signed int 足够宽,可以容纳所有 unsigned char 值,在第二个中,您显式地将值设置为正值。)

@cdhowie's post is nearly correct. However, if you cast to a char (signed or unsigned), the standard stream operators will attempt to write out the ASCII value of that character. You will either need another cast:

static_cast<int>(static_cast<unsigned char>(dec[i]))

or to explicitly truncate the value:

(static_cast<int>(dec[i]) & 0xFF)

(In both cases, your outer int does not need to be unsigned; in the first case, signed int is wide enough to hold all unsigned char values, and in the second, you are explicitly making the value positive.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文