解码和编码问题。android.util.* 和 java.util.* 中 Base64 类的不同实现?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22696126/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 17:20:03  来源:igfitidea点击:

Decoding and Encoding issue. Different implementations of Base64 Class in android.util.* and java.util.*?

javaandroidencodingbase64decoding

提问by user3469811

I am writing an App which does the following with a given String str:

我正在编写一个应用程序,它使用给定的字符串 str 执行以下操作:

encode(encrypt(encode(stringToBytearray(str))));

The Server receives the Base64 encoded String, which is then decoded -> decrypted -> decoded, to get the sent String str from the App.

Server接收Base64编码的String,然后解码->解密->解码,得到App发送的String str。

Unfortunately it doesnt work for all Strings, long Strings lead to a long Base64 String and my Server throws the following Exception:

不幸的是,它不适用于所有字符串,长字符串导致长 Base64 字符串,我的服务器抛出以下异常:

Exception in thread "main" java.lang.IllegalArgumentException: Illegal base64 character 5b
 at java.util.Base64$Decoder.decode0(Base64.java:714)
 at java.util.Base64$Decoder.decode(Base64.java:526)
 at Main.decode(Main.java:113)
 at Main.main(ain.java:33)

The String has the format "[string, string, ..., string]" without "s.

String 的格式为“[string, string, ..., string]”,没有“s”。

Like I mentioned above, for Strings which are not too long (sorry I cant quantify the length yet), this works. So I think I implemented it right.

就像我上面提到的,对于不太长的字符串(对不起,我还不能量化长度),这是有效的。所以我认为我实施它是正确的。

Whats weird is, that if I dont send it, but decode(decrypt(decode(stringToBytearray(str)))); the String on the Device itself, it all works perfectly.

奇怪的是,如果我不发送它,而是 decode(decrypt(decode(stringToBytearray(str)))); 设备本身上的字符串,一切都完美无缺。

My Setup: JDK 7, eclipse (adt-bundle, android development) (Windows 7)

我的设置:JDK 7,eclipse(adt-bundle,android 开发)(Windows 7)

JDK 8, eclipse ('normal' java) (Linux (xubuntu))

JDK 8, eclipse ('normal' java) (Linux (xubuntu))

Is it because both Classes (Base64) are implemented diffrently? If so, how can I make it work?

是因为两个类(Base64)的实现方式不同吗?如果是这样,我怎样才能使它工作?

Here are the Encoding/Decoding Methods:

以下是编码/解码方法:

Encoding (Device: on Windows 7, adt-bundle, Android-Dev, jdk 7):

编码(设备:Windows 7、adt-bundle、Android-Dev、jdk 7):

import android.util.Base64

public byte[] encode(byte[] bytearrayToEncode){
   return Base64.encode(bytearrayToEncode, Base64.NO_WRAP|Base64.URL_SAFE);
}

Decoding (Server: on Linux, jdk 8):

解码(服务器:Linux,jdk 8):

import java.util.Base64

public byte[] decode(byte[] bytearrayToEncode){
   return Base64.getUrlDecoder().decode(bytearrayToDecode);
}

Strings are all De-/Encoded with the same charset (utf-8)! Encoding/Decoding: Base64

字符串都使用相同的字符集 (utf-8) 进行解码/编码!编码/解码:Base64

Crypto: AES

加密:AES

If you need more Information, just ask, but I think I provided all neccessary informations.

如果您需要更多信息,请问,但我想我提供了所有必要的信息。

Edit:

编辑:

public String bytearrayToString(byte[] bytearray){
    String str = null;
    try {
        str = new String(bytearray, "UTF-8");
    } catch (UnsupportedEncodingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return str;
}

public byte[] stringToBytearray(String str){
    byte[] bytearray = null;
    try {
        bytearray = str.getBytes("UTF-8");
    } catch (UnsupportedEncodingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return bytearray;
}

回答by Mohsin Ali

You must be using JSONObjects to send the Base64 String to the server. If so then the JSONObject will add " \ " escape characters to the string which are illegal Base64 characters. All you need to do is

您必须使用 JSONObjects 将 Base64 字符串发送到服务器。如果是这样,那么 JSONObject 将向字符串添加“\”转义字符,这些字符是非法 Base64 字符。你需要做的就是

String rectifiedString = Base64String.replace("\","");

on the server end before using the acquired string.

在使用获取的字符串之前在服务器端。

Optional

可选的

Also on the server side use

也在服务器端使用

import javax.xml.bind.DatatypeConverter;

and

String result = DatatypeConverter.printBase64Binary(bytearrayToDecode);

String result = DatatypeConverter.printBase64Binary(bytearrayToDecode);

byte[] result = DatatypeConverter.parseBase64Binary(str);

instead.

反而。

It will not only get the job done but is much faster at encoding/decoding (as benchmarked here).

它不仅可以完成工作,而且在编码/解码方面要快得多(如此处的基准测试)。

回答by Anand Varkey Philips

If you have a space in your encoded string, which is an illegal character in base64. If you remove it, it still generates the same image/data in the converter you linked to, and can be now decoded by your code as well.

如果编码字符串中有空格,这是 base64 中的非法字符。如果您删除它,它仍然会在您链接到的转换器中生成相同的图像/数据,并且现在也可以通过您的代码进行解码。

UPDATE:Some decoders (like the one you linked, or Base64.getMimeDecoder() in Java) ignore illegal characters, others (like Base64.getDecoder()) don't allow them.

更新:一些解码器(比如你链接的那个,或者 Java 中的 Base64.getMimeDecoder())忽略非法字符,其他的(比如 Base64.getDecoder())不允许它们。

回答by Leonardo Borges

Use for encode:

用于编码:

Base64.getEncoder().encodeToString(yourString.getBytes("UTF-8"));

and decode:

并解码:

byte[] decodedBytes = Base64.getDecoder().decode(yourString);
String stringDecode = new String(decodedBytes, "UTF-8");