诚心请教关于 base64 的问题

2020-11-03 16:44:15 +08:00
 Chaox

一直很疑惑 base64 的作用。我们传输文件不管是文本文件还是二进制文件最后都是二进制,文本文件只是对二进制的一种处理而显示出文本。 传输文件时,如果我们是用 ASCII 码传输,传输到对方后,对方也有 ASCII 码解释就可以了。其他编码如 UTF-8 之类也是如此。为什么需要 base64 ?

在网上看到这么一段话:

我们知道在计算机中任何数据都是按 ascii 码存储的,而 ascii 码的 128 ~ 255 之间的值是不可见字符。而在网络上交换数据时,比如说从 A 地传到 B 地,往往要经过多个路由设备,由于不同的设备对字符的处理方式有一些不同,这样那些不可见字符就有可能被处理错误,这是不利于传输的。所以就先把数据先做一个 Base64 编码,统统变成可见字符,这样出错的可能性就大降低了。

这里为什么不同设备处理方式会有不同呢,传输过程中不都是二进制吗,直接把二进制传给对方不就可以了?

4877 次点击
所在节点    程序员
41 条回复
ipwx
2020-11-03 16:46:38 +08:00
HTML / HTTP 这一套对不可见字符就不太友善。你可以看看相关标准。
FutherAll
2020-11-03 16:51:38 +08:00
直接传二进制没办法保证二进制安全?
P0P
2020-11-03 16:53:39 +08:00
很多古老的协议对二进制传输支持不好,或者很多场景下二进制编码受限,比如 FTP 协议就需要指明是 Text mode 还是 Binary mode
icyalala
2020-11-03 17:06:50 +08:00
如果你按二进制传输,那无所谓内容了。
但是你要按文本文件传输,那二进制内容就放不进来。

举个例子,服务端和客户端通信都是用 JSON 格式,JSON 按标准是 UTF-8 Only 的,
如果服务端想通过 JSON 传递一张 PNG 格式的验证码图片,那这个图片是二进制的就有问题了。
比如二进制里有 '\0' 字符,而这算作 ASCII 字符串的终止符,显然不行。
这时只能先 base64 编码一下才能放到 JSON 里。
julyclyde
2020-11-03 18:59:00 +08:00
传说古代有些设备是 7bit 的
不过我没有真见过,也没听说过具体型号
unixeno
2020-11-03 20:29:13 +08:00
base64 的意义就是全部用可见字符来表示一段二进制
不是所有地方都是按二进制处理的,比如 url,比如网页
这种地方你要想包含一段二进制,特别是包含不可见字符和非法字符的二进制,就必须先用可见字符编码
虽然这个用 16 进制来表示也可以,但是 base64 比 16 进制更省空间
CEBBCAT
2020-11-03 20:32:13 +08:00
base64 是一种映射,这种映射我不能很好地解释,去看编码过程就明白了,相信楼主八成也明白是怎样变幻的。

在我看来楼主贴的那段引用有不少错误的地方:

> 我们知道在计算机中任何数据都是按 ascii 码存储的
存储的是二进制,ASCII 是一种编码

> 而 ascii 码的 128 ~ 255 之间的值是不可见字符
ASCII 只定义了 128 个字符

后面的就不说了,我也一瓶子不满。关于为什么有时候需要使用 base64 对数据进行编码,可以认为这是对协议的一种妥协吧,比如楼上说的 JSON 或 HTTP,而 TCP 协议由于定义了数据长度,所以可以直接传递二进制数据而不需转义。

HTTP 的结束符号应该是两个\n 还是什么的,可以查看一下维基百科或者相关标准文件,RFC ISO 之类的。

JSON 的话,假如你想在一个 k-v 的 v 中存入一个带"的字符串,那么为了避免出现读取错误,你只好使用转义或者 base64 这种方式来 escape
dddd1919
2020-11-04 00:00:47 +08:00
如果需要文本保存的场景比如数据库,还是很有用的
Jirajine
2020-11-04 00:28:21 +08:00
base64 类似 hex 的作用,不过更省空间。
Corua
2020-11-04 02:16:43 +08:00
面向文本与面向字节的区别 @Jirajine #9 4 个字符表示原本 3 字节的数据 更占空间了才是
Phariel
2020-11-04 03:21:15 +08:00
这样做的好处是 信息在传输过程中不会丢失 不然如果遇到传递环节中节点系统不识别不接受不兼容字符 就可能传递不下去或者替换不兼容字符为其他兼容字符造成信息噪点污染数据
Mutoo
2020-11-04 07:33:34 +08:00
举个简单的例子:文本转输协议常常以标准的 c_str 为截体,\0 作为截止符。而二进制数据中很可能存在或多或少的 \0,(还有很多不可见的控制字符),直接放在这样的协议上是传输不了的。base64 解决的就是在文本转输协议上发送二进制数据的问题。
reus
2020-11-04 07:37:25 +08:00
传输当然不都是二进制
lmmortal
2020-11-04 07:51:55 +08:00
@Jirajine 为什么说 base64 比 hex 更省空间呢?随手试了下:11111111 用 hex 表示是 FF,转换成 base64 就不止两位了
dcoder
2020-11-04 08:02:37 +08:00
@Chaox
跟中间路由设备应该无关...
应该是端到端的 HTTP encoding/decoding prefer 纯文本, 规定这样更 reliable
opengps
2020-11-04 08:15:22 +08:00
其实都是不同层面的封装,类比想想阿波罗 64K 内存能上天,开发难度有多大,再看看你大的 helloworld 的包
二进制的确是 object,计算机世界的万物之本,1bit,
然后,8 个 bit 可一表示 1byte,可以表示数字,字母,这时候 ascii
然后,2-3 个 byte,就可以上升到各个国家语言字符了,这时候比如是 unicode
再然后,同样道理用来干别的,比如表示 rgb 的三原色 #001122
然后的然后,就是你现在看到的了

未来的安装包会更大,当然存储已经允许,正如三体中描述的:来自 21 世纪的古老病毒
t6attack
2020-11-04 08:21:31 +08:00
以这个 rsa 加解密的简单演示为例: https://v2ex.com/t/542798#r_6999455
如果加密后的数据不用 base64 编码的话,是无法直接显示在页面上的,显示了也是乱码。乱码复制粘贴到别处就是另一份数据了,文本格式就没问题。包括 rsa 的密钥对,想写进代码里,就必须用文本格式。
这就是文本格式的可读性、兼容性。

所谓的 hex,是 16 进制数据文本化。比如,你用二进制编辑器打开一份数据,肉眼可见的,就是 16 进制数据的文本化表达。HEX 只能用 16 个字符表达数据,的其他文本都浪费了。当然比 base64 浪费空间。
msg7086
2020-11-04 08:43:10 +08:00
不是所有的用例都支持二进制。

比如打印在纸上的时候就不能用二进制,显示在屏幕上也不行。
Bromine0x23
2020-11-04 09:42:00 +08:00
@lmmortal 一字节太短了,HEX 是 4bit 一字符,Base64 是 6bit 一字符,加上 Base64 要进行填充,最后长度会是 4 的倍数
0xFF(8bit) 的时候就是 2 vs 4,但是到 0xFFFF(16bit) 就是 4 vs 4 一样长了,0xFFFFFF (24bit) 是 6 vs 4 就反超了
xx6412223
2020-11-04 09:52:53 +08:00
在网络模型中,一般只有最底端的物理层才以二进制传输,而其他的要读取数据包中地址 /端口 /长度等等

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/721443

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX