0

我正在尝试将字符串从 base64 解码为 UTF-8 以进行分配。

有一段时间没有编写 Java 了,我可能没有使用最有效的方法,但是我设法实现了一个 99% 正确工作的函数。

Decoding the example string in Base64: VGhpcyBpcyBhbiBBcnhhbiBzYW1wbGUgc3RyaW5nIHRoYXQgc2hvdWxkIGJlIGVhc2lseSBkZWNvZGVkIGZyb20gYmFzZTY0LiAgSXQgaW5jbHVkZXMgYSBudW1iZXIgb2YgVVRGOCBjaGFyYWN0ZXJzIHN1Y2ggYXMgdGhlIPEsIOksIOgsIOcgYW5kICYjOTYwOyBjaGFyYWN0ZXJzLg==

结果: 这是一个 Arxan 示例字符串,应该很容易从 base64 解码。它包括许多 UTF8 字符,例如 ñ、é、è、ç 和 π 字符。

但是,在 π 的位置应该是输出的 π 符号。

请注意,我删除了 ; 在这里 π 之后,似乎 Stackoverflow 自动将其更正为 π

我已经尝试了很多事情,例如创建一个字节数组并打印它,但仍然无法正常工作。

我正在使用 Eclipse,是否只是那里的输出显示不正确?

有人建议让它工作吗?

谢谢,文森特

这是我的代码:

package base64;

import java.nio.ByteBuffer;
import java.nio.charset.Charset;

public class Base64 {

    public static void main(String[] args) {
        //Input strings

        String base64 = "VGhpcyBpcyBhbiBBcnhhbiBzYW1wbGUgc3RyaW5nIHRoYXQgc2hvdWxkIGJlIGVhc2lseSBkZWNvZGVkIGZyb20gYmFzZTY0LiAgSXQgaW5jbHVkZXMgYSBudW1iZXIgb2YgVVRGOCBjaGFyYWN0ZXJzIHN1Y2ggYXMgdGhlIPEsIOksIOgsIOcgYW5kICYjOTYwOyBjaGFyYWN0ZXJzLg==";
        //String base64 = "YW55IGNhcm5hbCBwbGVhc3U=";
        String utf8 = "any carnal pleas";

        //Base64 to UTF8
        System.out.println("Base64 conversion to UTF8");
        System.out.println("-------------------------");
        System.out.println("Input base64-string: " + base64);
        System.out.println("Output UTF8-string: " + stringFromBase64(base64));

        System.out.println();       

        //UTF8 to Base64
        System.out.println("UTF8 conversion to base64");
        System.out.println("-------------------------");
        System.out.println("Input UTF8-string: " + utf8);
        System.out.println("Output base64-string: " + stringToBase64(utf8));
        System.out.println();
        System.out.println("Pi is π");

    }

    public static String stringFromBase64(String base64) {
        StringBuilder binary = new StringBuilder();

        int countPadding = countPadding(base64); //count number of padding symbols in source string
        //System.out.println("No of *=* in the input is : " + countPadding);
        //System.out.println(base64);       

        for(int i=0; i<(base64.length()-countPadding); i++)
        {       
            int base64Value = fromBase64(String.valueOf(base64.charAt(i))); //convert Base64 character to Int
            String base64Binary = Integer.toBinaryString(base64Value);  //convert Int to Binary string
            StringBuilder base64BinaryCopy = new StringBuilder(); //debugging

            if (base64Binary.length()<6) //adds required zeros to make 6 bit string
            {           

                for (int j=base64Binary.length();j<6;j++){
                    binary.append("0");
                    base64BinaryCopy.append("0"); //debugging
                }
                base64BinaryCopy.append(base64Binary); // debugging
            } else // debugging
            {
                base64BinaryCopy.append(base64Binary); //debugging

            } // debugging

            //System.out.println(base64.charAt(i) + " = " + base64Value + " = " + base64BinaryCopy); //debugging

            binary.append(base64Binary);            
        }

        //System.out.println(binary);
        //System.out.println(binary.length());


        StringBuilder utf8String = new StringBuilder();


        for (int bytenum=0;bytenum<(binary.length()/8);bytenum++) //parse string Byte-by-Byte
        {
            StringBuilder utf8Bit = new StringBuilder();
            for (int bitnum=0;bitnum<8;bitnum++){
                utf8Bit.append(binary.charAt(bitnum+(bytenum*8)));

            }

            char utf8Char = (char) Integer.parseInt(utf8Bit.toString(), 2); //Byte to utf8 char     
            utf8String.append(String.valueOf(utf8Char)); //utf8 char to string and append to final utf8-string  
            //System.out.println(utf8Bit + " = " + Integer.parseInt(utf8Bit.toString(), 2) + " = " + utf8Char + " = " + utf8String); //debugging
        }                   



        return utf8String.toString();   
    }


    public static String stringToBase64(String utf8) {
        StringBuilder binary = new StringBuilder();
        String paddingString = "";
        String paddingSymbols = "";

        for(int i=0; i<(utf8.length()); i++)
        {       
            int utf8Value = utf8.charAt(i); //convert utf8 character to Int
            String utf8Binary = Integer.toBinaryString(utf8Value);  //convert Int to Binary string
            StringBuilder utf8BinaryCopy = new StringBuilder(); //debugging

            if (utf8Binary.length()<8) //adds required zeros to make 8 bit string
            {           

                for (int j=utf8Binary.length();j<8;j++){
                    binary.append("0");
                    utf8BinaryCopy.append("0"); //debugging
                }
                utf8BinaryCopy.append(utf8Binary); // debugging
            } else // debugging
            {
                utf8BinaryCopy.append(utf8Binary); //debugging

            } // debugging

            //System.out.println(utf8.charAt(i) + " = " + utf8Value + " = " + utf8BinaryCopy);
            binary.append(utf8Binary);

        }

        if ((binary.length() % 6) == 2) {
            paddingString = "0000"; //add 4 padding zeroes
            paddingSymbols = "==";
        } else if ((binary.length() % 6) == 4) {
            paddingString = "00"; //add 2 padding zeroes
            paddingSymbols = "=";
        } 
        binary.append(paddingString); //add padding zeroes

        //System.out.println(binary);
        //System.out.println(binary.length());

        StringBuilder base64String = new StringBuilder();

        for (int bytenum=0;bytenum<(binary.length()/6);bytenum++) //parse string Byte-by-Byte per 6 bits
        {
            StringBuilder base64Bit = new StringBuilder();
            for (int bitnum=0;bitnum<6;bitnum++){
                base64Bit.append(binary.charAt(bitnum+(bytenum*6)));
            }
            int base64Int = Integer.parseInt(base64Bit.toString(), 2); //Byte to Int
            char base64Char = toBase64(base64Int); //Int to Base64 char 
            base64String.append(String.valueOf(base64Char)); //base64 char to string and append to final Base64-string  
            //System.out.println(base64Bit + " = " + base64Int + " = " + base64Char + " = " + base64String); //debugging
        }
        base64String.append(paddingSymbols); //add padding ==
        return base64String.toString(); 

    }

    public static char toBase64(int a) { //converts integer to corresponding base64 char
        String charBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        //charBase64 = new char[]{'A','B','C','D','E','F','G','H','I','J','K','L','M','N'};
        return charBase64.charAt(a);
    }

    public static int fromBase64(String x) { //converts base64 string to corresponding integer
        String charBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        return charBase64.indexOf(x);       
    }

    public static int countPadding(String countPadding) { //counts the number of padding symbols in base64 input string
        int index = countPadding.indexOf("=");
        int count = 0;
        while (index != -1) {
            count++;
            countPadding = countPadding.substring(index + 1);
            index = countPadding.indexOf("=");
        }
        return count;   
    }
}
4

1 回答 1

1

UTF8 是一种字符编码,可将给定的字符转换为 1、2 或更多字节。您的代码假定每个字节都应转换为一个字符。这对于确实通过 UTF8 转换为单字节的 ASCII 字符(如 a、b、c)工作得很好,但对于转换为多字节序列的 PI 等字符则不起作用。

您的算法效率极低,我会放弃它并使用现成的 ecnoder/decoder。JDK 8带有一个. Guavacommons-codec也可以。你的代码应该很简单

String base64EncodedByteArray = "....";
byte[] decodedByteArray = decoder.decode(base64EncodedByteArray);
String asString = new String(decodedByteArray, StandardCharSets.UTF_8);

或者,对于另一个方向:

String someString = "VGhpcyBpcyBhb...";
byte[] asByteArray = someString.getBytes(StandardCharSets.UTF_8);
String base64EncodedByteArray = encoder.encode(asBytArray);
于 2015-10-25T10:58:34.367 回答