为什么很多时候我们在传输数据的时候都使用base64编码,因为这样我们可以减少数据量的传输。

您所在的位置:网站首页 蓝牙传输数据需要网络吗 为什么很多时候我们在传输数据的时候都使用base64编码,因为这样我们可以减少数据量的传输。

为什么很多时候我们在传输数据的时候都使用base64编码,因为这样我们可以减少数据量的传输。

2024-07-09 16:15| 来源: 网络整理| 查看: 265

如果要处理或生成二进制数据,有时可能需要将此数据放入到String中。大多数内存中的数据都存储在字节型数组中,但是常常要将数组中的数据转换成十六进制(基为16)或二进制(基为2)的形式,以便显示、存储或传输。例如,可能希望在一个基于文本的文件(如XML文件)中包含一些二进制数据,用一个电子邮件发送它,或在非文本字符会引起问题的场合中会用到它。与十进制(基数为10)表示相比,采用十六进制表示更合理,因为十进制数在转换成一个以2为底的数之前不能反映原始的二进制结构。下面所示的数据表示是等价的:

二进制: 10010000 00000000 00000000 10101010 十六进制: 900000AA 十进制: 2415919274

十六进制和二进制显示格式的缺点在于它们较为冗长。二进制编码最不可取,其长度是原始数据长度的8倍。十六进制的String是较好的折衷,仅占用原始数据两倍的空间,但仍能提供有关数据比特位的一些信息。但是,十六进制字符,不能显示每个数字的二进制表示。而这对于分析二进制数据的一些类型而言是非常有用的。 

图2-2  十六进制表示

对于二进制编码而言还有另一种常用的字符串表示。Base64(基64)是这样一种文本表示,它使用4个字节的文本来表示3个字节的原始二进制数据。它将数据转换成一个如下所示的64个可打印的字符组成的序列:

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

字符“A”表示成二进制数是000000,字符“/”则对应111111。Base64是MIME(Multipurpose Internet Mail Extensions)标准的一部分,邮件中会使用这种格式来附加如图像这样的二进制内容。编码文本中的每个字符对应一个包含6个比特位的原始数据,因此要使用4个字符来表示3个字节的原始数据。如果数据长度不是3字节的倍数,那么在编码的String上需要增加一些填充字符(Base64标准使用“=”号来进行填充)。十六进制序列90000000AA将编码成以Base64表示的“kAAAAKo=”。这是一种比十六进制更为紧凑的表示方法,但是考虑到上例中的填充,对于更长的数据块这种差别更为显著。

将二进制数转换成一个String是有用的,尤其是在将数据放置在某个不允许“奇特字符”的地方时。但是如何从byte[]转变为“kAAAAKo=”和“90000000AA”呢?你可能会想到简单地使用前面介绍过的默认的 byte[]到String转换。Java 5及其更高版本可以通过使用静态的Arrays.toString方法来显示数组中的数据项:

byte[] data = readDataFromSomewhere(); System.out.println(Arrays.toString(data)); // in Java 5 但是这并不会给我们带来太大帮助。它使用默认的toString方法进行转换并打印数据的每个字节,结果将以二进制的补码的十进制显示。每个字节被显示为–128到127范围内的一个数字。对于90000000AA,上面的代码将显示如下结果:

[-112, 0, 0, 0, -86] Java将每个字节作为一个有符号的十进制数来处理。Java确实提供了将数值转换成十六进制和二进制数的方法,但是首先必须将数据转换成一个包含所有字节数值类型(如long或BigInteger)。源自Apache的开放源码的Jakarta Commons-Codec项目提供了可以在二进制数据和十六进制或Base64之间转换的类。为了从字节数组数据中得到十六进制或Base64字符串,可以使用org.apache.commons.codec.binary包中的Hex和Base64类。

Win98系统:c:\Windows  c:\Windows\system Winnt和Win2000系统:c:\Winntc:\Winnt\system32 Winxp系统:c:\Windows  c:\Windows\system32

import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.DecoderException;

try { // the Hex class uses char arrays for String data // convert hex String to byte[] data byte[] dataArray = Hex.decodeHex("900000AA".toCharArray()); // convert byte[] data to hex String char[] hexChars = Hex.encodeHex(dataArray); // the Base64 class uses byte arrays for both directions // convert base 64 String to byte[] data byte[] dataArray2 = Base64.decodeBase64("kAAAAKo=".getBytes()); // convert byte[] data into base 64 String byte[] base64Bytes = Base64.encodeBase64(dataArray2); String base64Str = new String(base64Bytes); } catch (DecoderException e) { e.printStackTrace(); } 为了将二进制字符编码为其他进制的数据或将数据编码为二进制字符,在同一个包中还提供了BinaryCodec类,但是它按照与其他编解码器相反的次序来编码二进制数字(BinaryCodec从最后一个字节开始编码,或按照小尾字节序(little-endian)编码)。这可能会引起一些混乱,因此推荐使用JDK的java.math.BigInteger类来替代BinaryCodec类(除非BinaryCodec以后转变成按大尾字节序)。使用BigInteger类可以轻松地将原始数据转换成一个由1和0组成的String:

Win98系统:c:\Windows  c:\Windows\system Winnt和Win2000系统:c:\Winntc:\Winnt\system32 Winxp系统:c:\Windows  c:\Windows\system32 byte[] dataArray = readDataFromSomewhere(); // create a BigInteger with a positive (1) sign, using these bytes BigInteger numeric = new BigInteger(1, dataArray); System.out.println(numeric.toString(2)); // print as base 2 string BigInteger类还允许按照其他基数(如16进制)显示数据。BigInteger允许的最大基数是36,因此不能采用此方法创建Base64字符串(无论如何Base64中的字符都不遵循相同的映射)。使用BigInteger类从另一个方向转换数据则存在严重缺陷,如从基2(或其他基)String转换到byte[]。BigInteger包含一个符号位(sign bit)并且转换有时将会在开头引入一个额外的零字节数据: byte[] data = new byte[] {-112, 0, 0, 0, -86}; // create a BigInteger from the raw data (1 = positive sign) BigInteger bigIntData = new BigInteger(1, data); System.out.println(bigIntData.toString(2)); // BEWARE!!!! // converting the data back into an array gives different data byte[] converted = bigIntData.toByteArray(); // this example will print [0, -112, 0, 0, 0, -86] System.out.println(Arrays.toString(converted)); 注意,上面的示例中出现了转换过程中创建的额外的零字节!补码的最高位被用作符号位。上面的示例中符号位是1,并且BigInteger在内部添加了一个零字节来维持正号。如果原始数据中第一个字节的最高位是0,byte[]表示将保持不变。大多数应用程序通常不需要从一个由1和0构成的String中读取二进制数据,但是它有时有助于将数据显示为一个二进制的字符串。但要谨慎使用BigInteger,仅将它作为一种显示原始数据而不是创建原始数据的手段。因此,更好还是使用Hex和Base64类。请参考网络上的资源以便了解更多有关Base64标准和Apache Commons-Codec项目的信息。二进制结构将在第5章中再次用到,使用一个称为Colt的API(可搜索BitVector类来了解更多的信息)。 


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3