Java Base64 解码结果意外不同

标签 java base64

我有一个透明的 1x1 GIF 文件,其中包含以下数据:

$ xxd pixel.gif
00000000: 4749 4638 3961 0100 0100 f000 0000 0000  GIF89a..........
00000010: 0000 0021 f904 0100 0000 002c 0000 0000  ...!.......,....
00000020: 0100 0100 0002 0244 0100 3b              .......D..;

该文件的Base64编码数据如下:

$ openssl base64 -in pixel.gif
R0lGODlhAQABAPAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==

如果我解码这个字符串,我会得到以下正确的输出:

$ echo 'R0lGODlhAQABAPAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==' | openssl base64 -d | xxd
00000000: 4749 4638 3961 0100 0100 f000 0000 0000  GIF89a..........
00000010: 0000 0021 f904 0100 0000 002c 0000 0000  ...!.......,....
00000020: 0100 0100 0002 0244 0100 3b

当尝试用 Java 解码这个字符串时,我得到了意想不到的结果。考虑这个示例 Java 程序:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

import java.nio.charset.StandardCharsets;

import java.util.Base64;

public class Decode {
    public static void main(String[] args) {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
            String line = reader.readLine();

            //System.out.println(line.getBytes());
            byte[] data = Base64.getDecoder().decode(line.getBytes());
            System.out.print(new String(data, 0, data.length, StandardCharsets.UTF_8));
        } catch (IOException e) {
            System.out.println("IOException reading System.in");
        }
    }
}

当我将编码的字符串通过管道传递给这个程序时,我得到以下结果

$ echo 'R0lGODlhAQABAPAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==' | java Decode | xxd
00000000: 4749 4638 3961 0100 0100 efbf bd00 0000  GIF89a..........
00000010: 0000 0000 0021 efbf bd04 0100 0000 002c  .....!.........,
00000020: 0000 0000 0100 0100 0002 0244 0100 3b    ...........D..

我可以在第 11 个字节看到 0xf0 的预期输出更改为 0xef。整个二进制字符串现在是 47 个字节长,而不是 43 个字节长。为什么 Java 会发生这种情况?

最佳答案

您不能将任意二进制数据转换为 UTF-8 字符串。 UTF-8是一种遵循一定规则的unicode编码(例如所有多字节序列必须以11或10作为高位开始,多字节序列的第一个字节告诉解码器这个多字节序列包含多少字节)

你真正想要的是直接写字节数组,而不是先把它转换成字符串:

byte[] data = Base64.getDecoder().decode(line.getBytes());
System.out.write(data);

关于Java Base64 解码结果意外不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59107247/

相关文章:

java - 如何将元素转换为小部件?

php - 如何为 openssl_private_decrypt() 提供私钥

html - 多个实例相同的数据 url 图片

java - 使 Quartz 调度程序在没有 JDBC 的情况下持久化

java - @PathVariable ("ownerId") String theOwner 和@PathVariable String theOwner 的区别

java - ActiveMq:超过允许的最大客户端连接数

android - 如何在不使用外部库的情况下在 Jetpack Compose 中显示 base64 编码的图像

javascript - Nativescript:用黑色空间代替照片缩略图

c - 我如何在 C 中进行 base64 编码(解码)?

java - 如何使用 JUnit 测试两个在 Java 中都有 main 方法的类(客户端和服务器)?