在 Java 开发中,Base64 解码是我每隔几天就会用到的操作——从 Kubernetes 环境变量中提取密钥、 读取 REST API 返回的二进制数据、在调试时检查 JWT 令牌。Java 内置的 java.util.Base64 类(自 JDK 8 起提供)提供三种解码器: getDecoder() 用于标准 Base64,getUrlDecoder() 用于 URL 安全输入,getMimeDecoder() 用于邮件附件等换行数据。如果只需快速验证而不想写代码, ToolDeck 的 Base64 解码器 可以直接在浏览器中完成。本文面向 Java 8+ 用户,涵盖三种解码器、使用 wrap(InputStream) 进行流式处理、提取 JWT 载荷、解码文件和 API 响应、 Apache Commons Codec 替代方案,以及四种在生产中导致乱码输出的常见错误。
- ✓Base64.getDecoder().decode(s) 是标准方式——自 JDK 8 起内置于 java.util.Base64,无需任何依赖。
- ✓处理 JWT 令牌和 OAuth 载荷时使用 getUrlDecoder()——它们使用 - 和 _ 字符集,而非 + 和 /。
- ✓getMimeDecoder() 会忽略换行符和空白字符,是处理邮件附件和 PEM 证书的正确选择。
- ✓decoder.wrap(InputStream) 支持大文件的动态解码,无需将全部内容加载到内存中。
- ✓基本解码器是严格的——尾部换行符、空格或错误的字符集字符会立即抛出 IllegalArgumentException。
什么是 Base64 解码?
Base64 编码将二进制数据转换为 64 个 ASCII 字符的表示形式,以便在纯文本通道中安全传输—— 包括 JSON 字段、HTTP 头、XML 文档、邮件正文。解码是其逆过程:每 4 个 Base64 字符还原为 3 个原始字节。末尾的 = 填充字符表示最后一组填充了多少字节。Base64 不是加密—— 任何人都可以还原它。其目的是保证传输安全,而非保密。
Java 中典型的解码场景:提取以 Base64 形式注入的配置值,解包云 API 响应中的二进制文件内容, 读取 PEM 编码的证书,以及在调试时检查 JWT 令牌载荷。
ZGItcHJvZC51cy1lYXN0LTEuYW1hem9uYXdzLmNvbTo1NDMy
db-prod.us-east-1.amazonaws.com:5432
Base64.getDecoder().decode() — 标准解码方法
java.util.Base64 类在 JDK 8 中引入,取代了过去大家依赖的 sun.misc.BASE64Decoder。无需外部依赖——只需 import java.util.Base64 并调用 Base64.getDecoder().decode()。该方法接受 String 或 byte[],并返回包含解码数据的 byte[]。
最简可运行示例
import java.util.Base64;
import java.nio.charset.StandardCharsets;
public class DecodeCredential {
public static void main(String[] args) {
// Kubernetes secret value, Base64-encoded
String encoded = "ZGItcHJvZC51cy1lYXN0LTEuYW1hem9uYXdzLmNvbTo1NDMy";
byte[] decodedBytes = Base64.getDecoder().decode(encoded);
String connectionString = new String(decodedBytes, StandardCharsets.UTF_8);
System.out.println(connectionString);
// db-prod.us-east-1.amazonaws.com:5432
}
}构造 String 时务必指定 StandardCharsets.UTF_8。 无参的 new String(bytes) 构造函数使用平台默认编码, 不同系统上的结果可能不同。在以 Cp1252 为默认编码的 Windows 服务器上, 多字节 UTF-8 字符会被悄无声息地损坏。
往返验证
import java.util.Base64;
import java.nio.charset.StandardCharsets;
public class RoundTrip {
public static void main(String[] args) {
String original = "redis://cache-prod.internal:6379/session-store";
String encoded = Base64.getEncoder().encodeToString(
original.getBytes(StandardCharsets.UTF_8)
);
System.out.println(encoded);
// cmVkaXM6Ly9jYWNoZS1wcm9kLmludGVybmFsOjYzNzkvc2Vzc2lvbi1zdG9yZQ==
byte[] decoded = Base64.getDecoder().decode(encoded);
String recovered = new String(decoded, StandardCharsets.UTF_8);
System.out.println(recovered.equals(original)); // true
}
}解码到预分配缓冲区
三参数重载 decode(byte[] src, byte[] dst) 直接写入目标缓冲区, 并返回写入的字节数。这可以在热路径上避免额外的内存分配:
import java.util.Base64;
public class DecodeToBuffer {
public static void main(String[] args) {
byte[] src = "eyJob3N0IjoiMTAuMC4xLjUwIiwicG9ydCI6ODQ0M30=".getBytes();
byte[] dst = new byte[1024]; // pre-allocated
int len = Base64.getDecoder().decode(src, dst);
String result = new String(dst, 0, len);
System.out.println(result);
// {"host":"10.0.1.50","port":8443}
}
}decode() 在输入包含 Base64 字符集之外的字符(包括换行符和空格)时, 会抛出 IllegalArgumentException。如果输入可能含有空白字符, 请换用 getMimeDecoder(),或在解码前调用 encoded.strip() 去除空白。解码 Base64 到非标准类型和自定义对象
decode() 返回的原始 byte[] 通常需要转换为更具体的类型: UUID、序列化的 Java 对象、protobuf 消息或时间戳。解码器本身始终返回字节—— 将其转换为领域类型是开发者的责任。
Base64 转 UUID
import java.util.Base64;
import java.nio.ByteBuffer;
import java.util.UUID;
public class DecodeUUID {
public static UUID fromBase64(String encoded) {
byte[] bytes = Base64.getUrlDecoder().decode(encoded);
ByteBuffer bb = ByteBuffer.wrap(bytes);
return new UUID(bb.getLong(), bb.getLong());
}
public static void main(String[] args) {
// Compact Base64-encoded UUID from an API response
String encoded = "f47ac10b-58cc-4372-a567-0e02b2c3d479";
UUID original = UUID.fromString(encoded);
// Encode to Base64 (compact form — 22 chars vs 36)
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(original.getMostSignificantBits());
bb.putLong(original.getLeastSignificantBits());
String compact = Base64.getUrlEncoder().withoutPadding()
.encodeToString(bb.array());
System.out.println(compact); // 9HrBC1jMQ3KlZw4CssPUeQ
// Decode back
UUID recovered = fromBase64(compact);
System.out.println(recovered); // f47ac10b-58cc-4372-a567-0e02b2c3d479
}
}Base64 转 Jackson 反序列化 JSON 对象
import java.util.Base64;
import java.nio.charset.StandardCharsets;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.Instant;
public class DecodeJsonPayload {
record DeployEvent(String service, String region, Instant deployedAt, int replicas) {}
public static void main(String[] args) throws Exception {
// Base64-encoded JSON payload from a message queue
String encoded = "eyJzZXJ2aWNlIjoicGF5bWVudC1nYXRld2F5Iiwi"
+ "cmVnaW9uIjoiZXUtd2VzdC0xIiwiZGVwbG95ZWRBdCI6"
+ "IjIwMjYtMDMtMTVUMTQ6MzA6MDBaIiwicmVwbGljYXMiOjR9";
byte[] jsonBytes = Base64.getDecoder().decode(encoded);
String json = new String(jsonBytes, StandardCharsets.UTF_8);
System.out.println(json);
// {"service":"payment-gateway","region":"eu-west-1",
// "deployedAt":"2026-03-15T14:30:00Z","replicas":4}
ObjectMapper mapper = new ObjectMapper();
mapper.findAndRegisterModules(); // picks up JavaTimeModule
DeployEvent event = mapper.readValue(jsonBytes, DeployEvent.class);
System.out.println(event.service()); // payment-gateway
System.out.println(event.deployedAt()); // 2026-03-15T14:30:00Z
}
}ObjectInputStream 反序列化不可信的 Base64 数据。Java 反序列化攻击已有大量文档记录——如果编码内容来自外部来源,请将其解析为 JSON 或 protobuf, 而非使用 Java 原生序列化。Base64.Decoder 方法参考
所有方法均属于 java.util.Base64 及其内部类 Base64.Decoder。Base64 上的三个工厂方法返回不同的解码器实例;decode() 和 wrap() 方法位于 Decoder 实例上。
getMimeDecoder() — 解码换行及 MIME Base64
基本解码器会拒绝 Base64 字符集之外的任何字符——包括 MIME 编码内容中必然存在的 \r\n 换行符。邮件附件、PEM 证书以及一些较老的 API 响应会在每行 76 个字符处换行。getMimeDecoder() 会静默忽略换行符及任何不在 Base64 字符集中的字符,因此可以开箱即用地处理这类数据。
import java.util.Base64;
import java.nio.charset.StandardCharsets;
public class MimeDecode {
public static void main(String[] args) {
// PEM certificate body — line-wrapped at 76 characters
String pemBody = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t\r\n"
+ "TUlJQm96Q0NBVWlnQXdJQkFnSUpBSXBhVDJU\r\n"
+ "aVFvZU1BMEdDU3FHU0liM0RRRU==";
// getDecoder() would throw IllegalArgumentException here
byte[] decoded = Base64.getMimeDecoder().decode(pemBody);
System.out.println(new String(decoded, StandardCharsets.UTF_8));
// -----BEGIN CERTIFICATE-----
// MIIBozCCAUigAwIBAgIJAIpaT2T...
}
}getMimeDecoder() 是宽松模式:它会跳过无效字符而非抛出异常。 对于已知的 MIME 数据来说没有问题,但对于任意输入,它可能会悄无声息地忽略数据损坏。 当需要严格验证时,请使用 getDecoder()。从文件和 API 响应中解码 Base64
从磁盘读取 Base64 编码的文件
二进制文件(图像、证书、加密 blob)有时以 Base64 文本形式存储在磁盘上。 读取文件、解码、写入二进制输出:
import java.util.Base64;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class DecodeFile {
public static void main(String[] args) {
Path inputPath = Path.of("tls-cert.pem.b64");
Path outputPath = Path.of("tls-cert.pem");
try {
String encoded = Files.readString(inputPath).strip();
byte[] decoded = Base64.getMimeDecoder().decode(encoded);
Files.write(outputPath, decoded);
System.out.printf("Decoded %d bytes → %s%n", decoded.length, outputPath);
} catch (IOException e) {
System.err.println("File error: " + e.getMessage());
} catch (IllegalArgumentException e) {
System.err.println("Invalid Base64: " + e.getMessage());
}
}
}解码 HTTP API 响应中的 Base64 字段
云 API(AWS KMS、GitHub Contents、Vault)经常在 JSON 中以 Base64 字符串形式返回二进制数据。 先解析 JSON,再解码目标字段:
import java.util.Base64;
import java.nio.charset.StandardCharsets;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class DecodeApiResponse {
public static void main(String[] args) {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/secrets/db-password"))
.header("Authorization", "Bearer sk-prod-9f8e7d6c")
.build();
try {
HttpResponse<String> response = client.send(
request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
System.err.printf("Unexpected status: %d%n", response.statusCode());
return;
}
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(response.body());
// API returns: {"name":"db-password","value":"cG9zdGdyZXM6eGs5...","version":3}
String encodedValue = root.get("value").asText();
byte[] decoded = Base64.getDecoder().decode(encodedValue);
String secret = new String(decoded, StandardCharsets.UTF_8);
System.out.println("Secret: " + secret);
// Secret: postgres:xk9mP2qR@db-prod:5432/orders
} catch (Exception e) {
System.err.println("Failed to fetch secret: " + e.getMessage());
}
}
}IllegalArgumentException 的 try-catch 中, 与网络错误的异常处理分开。将 I/O 异常和解码失败混在一起会增加调试难度—— 你需要立即判断是 API 返回了错误数据还是网络出现了故障。从命令行进行 Base64 解码
并非每次都需要编写 Java 程序。每台 Linux 和 macOS 系统都有 base64 命令, JDK 9+ 还提供了 jshell 用于交互式 Java 单行命令。 在调试时,这些方式比编译一个类要快得多。
# Decode a Base64 string (Linux / macOS)
echo "eyJob3N0IjoiMTAuMC4xLjUwIiwicG9ydCI6ODQ0M30=" | base64 --decode
# {"host":"10.0.1.50","port":8443}
# Decode and pretty-print with jq
echo "eyJob3N0IjoiMTAuMC4xLjUwIiwicG9ydCI6ODQ0M30=" | base64 --decode | jq .
# {
# "host": "10.0.1.50",
# "port": 8443
# }
# Quick decode with jshell (JDK 9+)
echo 'System.out.println(new String(java.util.Base64.getDecoder().decode("c2VydmVyLWNvbmZpZw==")))' | jshell -
# server-config
# macOS uses -D instead of --decode
echo "c2VydmVyLWNvbmZpZw==" | base64 -D如果需要将编码字符串直接粘贴到浏览器中验证, ToolDeck 的 Base64 解码器 无需任何配置即可处理标准和 URL 安全两种变体。
高性能替代方案:Apache Commons Codec
Java 内置的 java.util.Base64 已经经过充分优化——JDK 11+ 在 x86 上对编解码 使用了 intrinsic 优化。对大多数应用而言,没有理由引入第三方库。话虽如此,Apache Commons Codec 在遗留代码库中仍然很流行,并提供 Base64InputStream,支持带自动空白字符 处理的流式解码。
<!-- pom.xml -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.17.0</version>
</dependency>import org.apache.commons.codec.binary.Base64;
public class CommonsCodecDecode {
public static void main(String[] args) {
// Commons Codec is more lenient — handles whitespace and line breaks
String encoded = "eyJob3N0IjoiMTAuMC4xLjUw\nIiwicG9ydCI6ODQ0M30=";
byte[] decoded = Base64.decodeBase64(encoded);
System.out.println(new String(decoded));
// {"host":"10.0.1.50","port":8443}
}
}Commons Codec 相比内置 API 的主要优势在于默认对空白字符更宽松,以及其 Base64InputStream 类——该类早于 Java 的 decoder.wrap()。 如果你使用 Java 8+,内置 API 已经覆盖了 Commons Codec 的所有功能。 我只在项目已经依赖它的情况下才会使用 Commons Codec。
使用 decoder.wrap() 流式处理大型 Base64 文件
用 Files.readString() 加载一个 200 MB 的 Base64 文件再调用 decode(),大约需要分配 350 MB 的堆内存:编码字符串加上解码后的字节数组。decoder.wrap(InputStream) 在读取时动态解码,使内存占用保持恒定。
import java.util.Base64;
import java.io.*;
import java.nio.file.*;
public class StreamDecode {
public static void main(String[] args) throws IOException {
Path src = Path.of("database-dump.sql.b64");
Path dst = Path.of("database-dump.sql");
try (InputStream in = Base64.getMimeDecoder().wrap(
new BufferedInputStream(Files.newInputStream(src)));
OutputStream out = new BufferedOutputStream(Files.newOutputStream(dst))) {
byte[] buffer = new byte[8192];
int bytesRead;
long total = 0;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
total += bytesRead;
}
System.out.printf("Decoded %d bytes → %s%n", total, dst);
}
}
}在 Java 9+ 上,可以用 in.transferTo(out) 替换读取循环—— 效果相同但代码更简洁。如果文件可能包含换行符(PEM 文件、邮件导出), 请使用 getMimeDecoder().wrap() 而非 getDecoder().wrap()。
import java.util.Base64;
import java.io.*;
import java.nio.file.*;
public class StreamDecodeSimple {
public static void main(String[] args) throws IOException {
try (InputStream in = Base64.getMimeDecoder().wrap(
new BufferedInputStream(Files.newInputStream(Path.of("backup.tar.b64"))));
OutputStream out = Files.newOutputStream(Path.of("backup.tar"))) {
in.transferTo(out); // Java 9+
}
}
}getDecoder().wrap() 不能容忍流中的换行符。 如果 Base64 数据有换行符(每 76 个字符换行),请改用 getMimeDecoder().wrap()——否则流会在不可预知的读取位置产生损坏的输出或抛出异常。在 Java 中无需 JWT 库解码 Base64 JWT 载荷
JWT 由三个 Base64url 编码的段通过点号连接而成。中间的段是载荷——也是调试时最关心的部分。 无需引入 jjwt 或 Nimbus 即可解码。以 . 分割,用 getUrlDecoder() 解码第二段,再解析得到的 JSON:
import java.util.Base64;
import java.nio.charset.StandardCharsets;
public class JWTInspect {
public static String decodeJwtPayload(String token) {
String[] parts = token.split("\\.");
if (parts.length != 3) {
throw new IllegalArgumentException(
"Invalid JWT: expected 3 segments, got " + parts.length);
}
// JWT uses URL-safe Base64 without padding
byte[] payload = Base64.getUrlDecoder().decode(parts[1]);
return new String(payload, StandardCharsets.UTF_8);
}
public static void main(String[] args) {
String token = "eyJhbGciOiJSUzI1NiJ9"
+ ".eyJzdWIiOiJ1c3ItNjcyIiwiaXNzIjoiYXV0aC5leGFtcGxlLmNvbSIs"
+ "ImV4cCI6MTc0MTk1NjgwMCwicm9sZXMiOlsiYWRtaW4iLCJiaWxsaW5nIl19"
+ ".SIGNATURE_PLACEHOLDER";
String payload = decodeJwtPayload(token);
System.out.println(payload);
// {"sub":"usr-672","iss":"auth.example.com",
// "exp":1741956800,"roles":["admin","billing"]}
}
}常见错误
这些错误我在代码审查中都遇到过,前两个占据了 Java 服务中绝大多数 Base64 相关的生产 bug。
问题: JWT 令牌和 OAuth 访问令牌使用 URL 安全字符集(- 和 _)。将它们传给 getDecoder() 会抛出 IllegalArgumentException,因为 - 不在标准 Base64 字符集中。
解决方案: 检查数据来源:来自认证系统的令牌需要 getUrlDecoder();MIME 附件需要 getMimeDecoder()。
// JWT header — URL-safe, no padding String header = "eyJhbGciOiJSUzI1NiJ9"; byte[] decoded = Base64.getDecoder().decode(header); // IllegalArgumentException: Illegal base64 character 2d
String header = "eyJhbGciOiJSUzI1NiJ9";
byte[] decoded = Base64.getUrlDecoder().decode(header);
System.out.println(new String(decoded));
// {"alg":"RS256"}问题: new String(bytes) 使用 JVM 默认字符集,不同环境下结果不同。Linux CI 服务器(UTF-8)和 Windows 生产主机(Cp1252)对相同字节会产生不同的结果。
解决方案: 始终将 StandardCharsets.UTF_8 作为第二个参数传入。
byte[] decoded = Base64.getDecoder().decode(encoded); String result = new String(decoded); // platform-dependent — may corrupt multi-byte characters
byte[] decoded = Base64.getDecoder().decode(encoded); String result = new String(decoded, StandardCharsets.UTF_8); // consistent across all platforms
问题: 从终端粘贴或从配置文件读取的 Base64 字符串通常带有尾部换行符。基本解码器会拒绝 Base64 字符集之外的任何字符。
解决方案: 在解码前调用 .strip() 去除空白,或换用 getMimeDecoder()——它会忽略空白字符。
// Read from environment variable — has a trailing newline
String encoded = System.getenv("DB_PASSWORD_B64"); // "cG9zdGdyZXM=
"
byte[] decoded = Base64.getDecoder().decode(encoded);
// IllegalArgumentException: Illegal base64 character aString encoded = System.getenv("DB_PASSWORD_B64");
byte[] decoded = Base64.getDecoder().decode(encoded.strip());
System.out.println(new String(decoded, StandardCharsets.UTF_8));
// postgres问题: 对二进制内容(图像、protobuf、加密 blob)调用 new String(decoded) 会产生无效的 String。之后再转回字节时会悄无声息地损坏数据,因为 String 构造函数会替换无效的 UTF-8 序列。
解决方案: 在整个处理流程中将二进制数据保持为 byte[]。只有在确认内容为文本时才转换为 String。
byte[] decoded = Base64.getDecoder().decode(pngBase64);
String imageStr = new String(decoded); // corrupts binary
Files.writeString(Path.of("image.png"), imageStr); // broken filebyte[] decoded = Base64.getDecoder().decode(pngBase64);
// Write bytes directly — no String conversion
Files.write(Path.of("image.png"), decoded);方法对比
内置解码器涵盖大多数使用场景。Apache Commons Codec 和 Guava 是可能在旧代码库中遇到的替代方案。
JWT 令牌和现代 API 载荷:使用 getUrlDecoder()。邮件附件和 PEM 证书: 使用 getMimeDecoder()。内存敏感的大文件:使用 decoder.wrap(InputStream)。 其他情况:使用 getDecoder()。只有当 Apache Commons Codec 已经在你的依赖树中时, 才考虑使用它。
开发过程中如需快速验证, 在线 Base64 解码器 比编写一次性的类更快。
常见问题
如何在 Java 中解码 Base64 字符串?
导入 java.util.Base64,调用 Base64.getDecoder().decode(encodedString)。方法返回 byte[]——用 new String(bytes, StandardCharsets.UTF_8) 包装即可得到可读文本。对于 URL 安全的 Base64(JWT 使用此格式),将 getDecoder() 换成 getUrlDecoder()。
import java.util.Base64;
import java.nio.charset.StandardCharsets;
byte[] decoded = Base64.getDecoder().decode("c2VydmVyLWNvbmZpZw==");
String result = new String(decoded, StandardCharsets.UTF_8);
System.out.println(result); // server-configJava 中 getDecoder() 和 getMimeDecoder() 有什么区别?
getDecoder() 是严格模式——它会拒绝 Base64 字符集之外的任何字符,包括换行符。getMimeDecoder() 则容忍换行符(\r\n)并忽略任何非 Base64 字符,因此它是解码邮件附件和 PEM 证书的正确选择——这些数据通常在每 76 个字符处换行。
String wrapped = "c2VydmVyLWNv\r\nbmZpZw=="; // getDecoder() throws IllegalArgumentException // Base64.getDecoder().decode(wrapped); // FAILS // getMimeDecoder() handles it byte[] decoded = Base64.getMimeDecoder().decode(wrapped); System.out.println(new String(decoded)); // server-config
如何在 Java 中解码 URL 安全的 Base64 字符串?
使用 Base64.getUrlDecoder().decode(encoded)。URL 解码器期望 RFC 4648 §5 定义的 - 和 _ 字符集,而非 + 和 /。JWT 令牌始终使用此字符集。如果填充字符(=)被去除(JWT 中常见),URL 解码器仍然可以处理——Java 的 URL 解码器同时支持带填充和不带填充的输入。
import java.util.Base64;
// JWT header — URL-safe, no padding
String jwtHeader = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
byte[] decoded = Base64.getUrlDecoder().decode(jwtHeader);
System.out.println(new String(decoded));
// {"alg":"HS256","typ":"JWT"}如何在 Java 中流式解码大型 Base64 文件?
使用 decoder.wrap(inputStream) 包装 FileInputStream。返回的 InputStream 在读取字节时动态解码 Base64,因此内存占用保持恒定,与文件大小无关。将其通过 BufferedInputStream 传输,或直接传给 Files.copy() 以获得最佳吞吐量。
import java.util.Base64;
import java.io.*;
import java.nio.file.*;
try (InputStream in = Base64.getDecoder().wrap(
new BufferedInputStream(new FileInputStream("payload.b64")));
OutputStream out = new FileOutputStream("payload.bin")) {
in.transferTo(out);
}为什么 Base64.getDecoder().decode() 会抛出 IllegalArgumentException?
基本解码器是严格的:它拒绝换行符、空格以及 A-Za-z0-9+/= 之外的任何字符。三种常见原因:输入有尾部换行符(调用 trim 去除),输入使用了 URL 安全字符如 - 和 _(换用 getUrlDecoder()),或者输入在 76 个字符处换行(换用 getMimeDecoder())。如果错误信息不明确,建议直接检查原始字节。
String raw = "c2VydmVyLWNvbmZpZw==\n"; // trailing newline // Option 1: trim whitespace byte[] decoded = Base64.getDecoder().decode(raw.strip()); // Option 2: use MIME decoder which ignores whitespace byte[] decoded2 = Base64.getMimeDecoder().decode(raw);
在 Java 中能否不使用 java.util.Base64 来解码 Base64?
可以,但在 Java 8+ 上没有充分的理由这样做。Java 8 之前,开发者使用 sun.misc.BASE64Decoder(内部 API,已在 Java 9+ 中移除)、javax.xml.bind.DatatypeConverter.parseBase64Binary()(已在 Java 11 中移除)或 Apache Commons Codec。这三种方式要么已弃用,要么需要额外依赖。建议坚持使用 java.util.Base64——它更快,随 JDK 一起提供,且涵盖全部三种变体(基本、URL 安全、MIME)。
相关工具
- Base64 Encoder — 在浏览器中将文本或二进制数据编码为 Base64,便于生成测试数据并粘贴到 Java 单元测试中。
- JWT Decoder — 一次性分割并解码 JWT 的三个段,逐字段检查载荷内容——比只需要读取令牌时编写 Java 类要快得多。
- URL Decoder — 对 URL 编码的字符串进行百分号解码,在 API 响应将 Base64url 数据与百分号编码的查询参数混合使用时非常有用。
- JSON Formatter — 解码 Base64 JWT 载荷或 API 配置后,将 JSON 粘贴到这里进行格式化并验证结构。