Java, Python 两种形式的 base64encode
在用 Python 写 Web 服务端代码时,用 base64.encodebytes() 函数对字符串进行编码,然后在 Java 端用 Base64.getDecoder().decode() 时无法解码,难道 base64 编码在两种语言间还有这等差异。Google 一下,得到的答案是在 Java 端要用 Base64.getMimeDecoder().decode() 函数解码。这一问题算是解决了, 不过后来又在 Python 写的 AWS Lambda 中输出
ChatGPT 的解决是在 Python 端用 base64.b64encode() 代替 base64.encodebytes(), 所以在 Python 和 Java 端有下面的对应关系
用一段代码来测试下 test.py
当字符串较短时,如输入
我看阅读 Java 的 Base64.getMimeEncoder() 的源码
然后是 RFC2045 的相关定义
每行宽度 76 个字符,用
最后重复一遍上面的
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。
return {以 AWS Lambda functionURL 的方式来访问,对于 body 中的小字符串是没问题,一旦 body 够大时在 Postman 或 curl 命令中无法直接展示出来,用 curl --output a.out 存成本地文件,打开后看到的是带换行的格式
"statusCode": 200,
"body": base64.encodebytes(b"short message"),
"isBase64Encoded": True
}
H4sIAAZi7GYC/+19WXfcOLLmX+HxwxzXOS6b2AhiprvnyFtZt7yoJbdr6r74UEpKyq5UpjoXL/fX这就是问题的所在,由 base64.encodebytes() 产生的 'body' 其实连 API Gateway 也无法自动解码出来,所以 base64 编码的内容才直接送到了客户端,原来 API Gateway 在看到 "isBase64Encoded": True 后会解码后送给请求端。
D8AlkysIkCFmpo2H7pJJEBkAAsCHQMQXf/t6HX/YrO83a++P168+xcvVdDH/+yP6lOGnzEciCNHn
gD7yTufT9evpLD6L1rd/f3Q6n03nsXexXk7nN4+8F4v59fRms4zW8uNtHdjH9KkfPEXoM6JPsf8U
......
ChatGPT 的解决是在 Python 端用 base64.b64encode() 代替 base64.encodebytes(), 所以在 Python 和 Java 端有下面的对应关系
base64.b64encode() <-> Base64.getDecoder().encode()相应的
base64.encodebytes() <-> Base64.getMimeDecoder().decode()
Base64.getEncoder().encode() <-> base64.b64decode()那么 Python 的 base64.b64encode() 与 base64.encodebytes() 有什么区别呢?或者说 Java 的 Base64.getEncoder().encode() 和 Base64.getMimeEncoder().encode() 有何不同?
Base64.getMimeEncoder().encode() <-> base64.decodebytes()
用一段代码来测试下 test.py
1import base64
2import sys
3
4repeat = int(sys.argv[1])
5source_str = b'hello' * repeat
6print('source str: \n', source_str.decode())
7
8print('\n----base64.encodebytes()----')
9print(base64.encodebytes(source_str).decode())
10
11print('\n----base64.b64encode()----')
12print(base64.b64encode(source_str).decode())当字符串较短时,如输入
python a.py 10而当字符串较大时
source str:
hellohellohellohellohellohellohellohellohellohello ----base64.encodebytes()----
aGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG8=
----base64.b64encode()----
aGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG8=
python a.py 50有没有对 base64.encodebytes() 这种格式很熟悉的感觉,就是像软件的注册文件的样式。base64.encodebytes() 会对产生的编码中插入换行符使得显示的时候更整洁些,看字符串内容的话会有许多的
source str:
hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello ----base64.encodebytes()----
aGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hl
bGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxs
b2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9o
ZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVs
bG9oZWxsb2hlbGxvaGVsbG9oZWxsbw==
----base64.b64encode()----
aGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsbw==
\r\n 换行字符,当等编码的字符串较短时(编码后未超过一行),base64.encodebytes() 与 base64.b64encode() 生成的结果是一样的。base64.b64encode() 才是原滋原味的 base64 编码, 它们之间除了格式化用的换行外没有别的区别了,所以用 base64.encodebytes() 编码的字符串手工去掉换行符,然后用 Base64.getDecoder().decode() 也可以解码出来。我看阅读 Java 的 Base64.getMimeEncoder() 的源码
1 public static Encoder getMimeEncoder() {
2 return Encoder.RFC2045;
3 }然后是 RFC2045 的相关定义
1 private static final int MIMELINEMAX = 76;
2 private static final byte[] CRLF = new byte[] {'\r', '\n'};
3
4 static final Encoder RFC2045 = new Encoder(false, CRLF, MIMELINEMAX, true);每行宽度 76 个字符,用
\r\n 分割,也就是前面看到的 base64.encodebytes() 产生长字符串的样子。最后重复一遍上面的
base64.b64encode() <-> Base64.getDecoder().encode() // 原味的 base64相应的
base64.encodebytes() <-> Base64.getMimeDecoder().decode() // 插入换行 的 base64
Base64.getEncoder().encode() <-> base64.b64decode() // 原味的 base64想当然 Java 的 Base64.getMimeEncoder().encode() 编码出来长字符串也应该是会插入换行符的,何不快速体验一下呢?
Base64.getMimeEncoder().encode() <-> base64.decodebytes() // 插入换行 的 base64
jshell> System.out.println(new String(Base64.getMimeEncoder().encode("hello".repeat(50).getBytes())));带附加换行符的 base64 只能用 base64.encodebytes() 和 Base64.getMimeDecoder().decode() 来解码,也就是说任何时候都可以用 base64.encodebytes() 或 Base64.getMimeDecoder().decode() 这两个函数进行 base64 解码,但编码的时候需看仔细。 永久链接 https://yanbin.blog/java-python-two-styles-base64encode/, 来自 隔叶黄莺 Yanbin's Blog
aGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hl
bGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxs
b2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9o
ZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVsbG9oZWxsb2hlbGxvaGVs
bG9oZWxsb2hlbGxvaGVsbG9oZWxsbw==
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。