1

我写了这个小转换器来将 Base2 文件数据转换为 Base64。结果输出不正确,我不知道为什么。如果将图像文件作为输入传递,则问题会更加复杂:将随机 NULL 字符 (0x00) 插入到输出中,这永远不会发生。输出应该只包含 Base64Table 的一个子集(参见代码)。


输入:

人之所以与众不同,不仅在于他的理性,而且在于这种与其他动物不同的独特激情,即心灵的欲望,通过对知识的持续和不知疲倦地产生的坚持不懈的快乐,超过任何肉体快乐的短暂激情.


预期输出:

TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4= 

(来自Base64 上的维基百科页面


实际输出:

YW7MaXPMZGnMdGnMZ3XMc2jMZCzMbm/MIG/MbHnMYnnMaGnMIHLMYXPMbizMYnXMIGLMIHTMaXPMc2nMZ3XMYXLMcGHMc2nMbiDMcm/MIG/MaGXMIGHMaW3MbHPMIHfMaWPMIGnMIGHMbHXMdCDMZiDMaGXMbWnMZCzMdGjMdCDMeSDMIHDMcnPMdmXMYW7MZSDMZiDMZWzMZ2jMIGnMIHTMZSDMb27MaW7MZWTMYW7MIGnMZGXMYXTMZ2HMbGXMZ2XMZXLMdGnMbiDMZiDMbm/MbGXMZ2XMIGXMY2XMZHPMdGjMIHPMb3LMIHbMaGXMZW7MZSDMZiDMbnnMY2HMbmHMIHDMZWHMdXLMLnLM

代码:

#include <iostream>
#include <fstream>

char Base64Table[64] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z', //0-25
                        'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z', //26-51
                        '0','1','2','3','4','5','6','7','8','9',                                                                 //52-61
                        '+','/'};                                                                                                //62-63
char PADDING_CHAR = '=';

char GetFirstSymbol(char* buffer);
char GetSecondSymbol(char* buffer);
char GetThirdSymbol(char* buffer);
char GetFourthSymbol(char* buffer);

int main(int argc, char** argv) {

    if(argc != 2) {
        std::cout << "Incorrect number of arguments." << std::endl;
        std::cout << "Press Enter to quit.";
        while(!std::cin.get());
        return 0;
    }

    std::cout << "Converting " << argv[1] << std::endl;

    std::ifstream input;
    input.open(argv[1], std::ios_base::binary);

    std::ofstream output;
    output.open("data.base64", std::ios_base::binary);

    char count[1] = {'\0'};
    unsigned long file_size = 0;
    char buffer[3] = {'\0', '\0', '\0'};
    while(input.fail() == false) {
        input.read(reinterpret_cast<char*>(count), sizeof(count));
        ++file_size;
    }
    input.clear();
    input.seekg(0);

    while(input.fail() == false) {
        input.read(reinterpret_cast<char*>(buffer), sizeof(buffer));
        char firstsymbol = GetFirstSymbol(buffer);
        char secondsymbol = GetSecondSymbol(buffer);
        char thirdsymbol = GetThirdSymbol(buffer);
        char fourthsymbol = GetFourthSymbol(buffer);

        output.write(reinterpret_cast<char*>(&firstsymbol), sizeof(firstsymbol));
        output.write(reinterpret_cast<char*>(&secondsymbol), sizeof(secondsymbol));
        if(file_size % 3 == 2) {
            output.write(reinterpret_cast<char*>(&PADDING_CHAR), sizeof(PADDING_CHAR));
            continue;
        } else if(file_size % 3 == 1) {
            output.write(reinterpret_cast<char*>(&PADDING_CHAR), sizeof(PADDING_CHAR));
            output.write(reinterpret_cast<char*>(&PADDING_CHAR), sizeof(PADDING_CHAR));
            continue;
        }
        output.write(reinterpret_cast<char*>(&thirdsymbol), sizeof(thirdsymbol));
        output.write(reinterpret_cast<char*>(&fourthsymbol), sizeof(fourthsymbol));
    }
    input.clear();
    input.close();

    output.clear();
    output.close();

    return 0;
}

//Gets the 6 most significant digits of the first byte.
char GetFirstSymbol(char* buffer) {
    int index = (buffer[1] >> 2);
    return Base64Table[index];
}

//Gets the 2 least significant digits from previous (first) byte and 4 most significant from the second byte.
char GetSecondSymbol(char* buffer) {
    int index = (((buffer[1] & 0x03) << 4) | ((buffer[2] & 0xF0) >> 4));
    return Base64Table[index];
}

//Gets the 4 least significant digits from previous (second) byte and 2 least significant from the third byte.
char GetThirdSymbol(char* buffer) {
    int index = (((buffer[2] & 0x0F) << 2) | ((buffer[3] & 0xC0) >> 6));
    return Base64Table[index];
}

//Gets the 6 least significant digits from the third byte.
char GetFourthSymbol(char* buffer) {
    int index = (buffer[3] & 0x3F);
    return Base64Table[index];
}
4

1 回答 1

2

C/C++ 指针和数组是非常强大的野兽,但它们也会伤害你!所以你在和他们一起工作时应该小心。您定义bufferchar[3]但从索引 [1] 到索引 [3] 访问它,这是您的错误,因为 C/C++ 数组的索引是基于 0 的,因此buffer [0][1][2][memory of other variables]您保持buffer[0]不变,而不是写入内存另一个变量,这是随机错误和无效值的原因!!!

于 2012-09-16T21:38:10.027 回答