1、为什么需要编码
计算机中存储信息的最小单元是一个字节即 8 个 bit,所以能表示的字符范围是 0~255 个;人类要表示的符号太多,无法用一个字节来完全表示;要解决这个矛盾必须需要一个新的数据结构 char,从 char 到 byte 必须编码。
2、各种常见编码的简介
- ASCII 码
学过计算机的人都知道 ASCII 码,总共有 128 个,用一个字节的低 7 位表示,0~31 是控制字符如换行回车删除等;32~126 是打印字符,可以通过键盘输入并且能够显示出来。
- ISO-8859-1
128 个字符显然是不够用的,于是 ISO 组织在 ASCII 码基础上又制定了一些列标准用来扩展 ASCII 编码,它们是 ISO-8859-1~ISO-8859-15,其中 ISO-8859-1 涵盖了大多数西欧语言字符,所有应用的最广泛。ISO-8859-1 仍然是单字节编码,它总共能表示 256 个字符。
- GB2312
它的全称是《信息交换用汉字编码字符集 基本集》,它是双字节编码,总的编码范围是 A1-F7,其中从 A1-A9 是符号区,总共包含 682 个符号,从 B0-F7 是汉字区,包含 6763 个汉字。
- GBK
全称叫《汉字内码扩展规范》,是国家技术监督局为 windows95 所制定的新的汉字内码规范,它的出现是为了扩展 GB2312,加入更多的汉字,它的编码范围是 8140~FEFE(去掉 XX7F)总共有 23940 个码位,它能表示 21003 个汉字,它的编码是和 GB2312 兼容的,也就是说用 GB2312 编码的汉字可以用 GBK 来解码,并且不会有乱码。
- GB18030
全称是《信息交换用汉字编码字符集》,是我国的强制标准,它可能是单字节、双字节或者四字节编码,它的编码与 GB2312 编码兼容,这个虽然是国家标准,但是实际应用系统中使用的并不广泛。
- UTF-16
说到 UTF 必须要提到 Unicode(Universal Code 统一码),ISO 试图想创建一个全新的超语言字典,世界上所有的语言都可以通过这本字典来相互翻译。可想而知这个字典是多么的复杂,关于 Unicode 的详细规范可以参考相应文档。Unicode 是 Java 和 XML 的基础,下面详细介绍 Unicode 在计算机中的存储形式。
UTF-16 具体定义了 Unicode 字符在计算机中存取方法。UTF-16 用两个字节来表示 Unicode 转化格式,这个是定长的表示方法,不论什么字符都可以用两个字节表示,两个字节是 16 个 bit,所以叫 UTF-16。UTF-16 表示字符非常方便,每两个字节表示一个字符,这个在字符串操作时就大大简化了操作,这也是 Java 以 UTF-16 作为内存的字符存储格式的一个很重要的原因。
- UTF-8
UTF-16 统一采用两个字节表示一个字符,虽然在表示上非常简单方便,但是也有其缺点,有很大一部分字符用一个字节就可以表示的现在要两个字节表示,存储空间放大了一倍,在现在的网络带宽还非常有限的今天,这样会增大网络传输的流量,而且也没必要。而 UTF-8 采用了一种变长技术,每个编码区域有不同的字码长度。不同类型的字符可以是由 1~6 个字节组成。
UTF-8 有以下编码规则:
- 如果一个字节,最高位(第 8 位)为 0,表示这是一个 ASCII 字符(00 - 7F)。可见,所有 ASCII 编码已经是 UTF-8 了。
- 如果一个字节,以 11 开头,连续的 1 的个数暗示这个字符的字节数,例如:110xxxxx 代表它是双字节 UTF-8 字符的首字节。
- 如果一个字节,以 10 开始,表示它不是首字节,需要向前查找才能得到当前字符的首字节
3、JAVA中的编码场景
JAVA是使用UTF-16,也就是定长的2个字节来进行编码,例如定义int为4byte,short为2byte。因为任何字符都是2字节的最小单元表示,所以处理起来很方便,但同时也会浪费空间,有些简单的字符只需要一个字节就可以表示,其本质就是用空间换时间。
JAVA中的编码场景主要有I/O操作和内存操作
1> I/O操作
例如InputStreamReader 就是从字节流到字符流的解码过程。而具体字节到字符的解码实现它由 StreamDecoder去实现,在 StreamDecoder解码过程中必须由用户指定 Charset编码格式。值得注意的是如果你没有指定 Charset,将使用本地环境中的默认字符集,例如在中文环境中将使用 GBK 编码。
OutputStreamWriter 转换字符到字节,同样 StreamEncoder 类负责将字符编码成字节,编码格式和默认编码规则与解码是一致的。
2>内存操作
String s = "字符串。。。";
byte[] bt = s.getBytes("UTF-8");
String str = new String(bt,"UTF-8");
String 类就提供转换到字节的方法,也支持将字节转换为字符串的构造函数。
Charset 提供 encode 与 decode 分别对应 char[] 到 byte[] 的编码和 byte[] 到 char[] 的解码。如下代码所示:
Charset charset = Charset.forName("UTF-8"); ByteBuffer byteBuffer = charset.encode(string); CharBuffer charBuffer = charset.decode(byteBuffer); |
字符和字节之间的相互转换只要我们设置编解码格式统一一般都不会出现问题。
4、Java Web 涉及到的编码
a.http://code.google.com/p/protobuf/downloads/list ,选择其中的win版本下载
b.下载一个protobuf-java-version.jar文件(注意,要与你刚才下的proto.exe版本相同,否则可能出现编译通不过现象)
c. 在proto.exe同级目录,编写一个.proto文件:支持message的嵌套,对应java的内部类。
d、使用protoc命令进行编译
2>序列化和反序列化分析
1、package与optionjava_package同时存在,后者会取代前者 。
java代码生成相关参考:https://developers.google.com/protocol-buffers/docs/reference/java-generated?hl=zh-CN
2、PB数据类型
required: a well-formed message must have exactly one of this field.
optional: a well-formed message can have zero or one of this field (but not more than one).
repeated: this field can be repeated any number of times (including zero) in a well-formed message. The order of the repeated values will be preserved.
类型参考https://developers.google.com/protocol-buffers/docs/proto?hl=zh-CN&csw=1
3、message的编码特点
PB之所以解析速度快、所占体积小,很大程度上是由它序列化的编码特点来决定的。
3.1 Base 128 Varints
PB采用了Base 128 Varints来变长编码整数:
变长编码的整数,它可能包含多个byte,对于每个byte的8位,其中后7位表示数值,最高的一位表示是否还有还有另一个byte,0表示没有,1表示有;
越前面的byte表示数值的低位,越后面的byte表示数值的高位;
例子:
300 varints 编码为:1010 1100 0000 0010
解释如下:
300的2进制编码为:0001 0010 1100
按照刚才的规则,高低位颠倒,截取最后的7为放在第一个byte,则第一byte为1010 1100(其中最高位1表示,后续还有byte);接着剩下的内容放到第二个byte,为0000 0010(其中最高位0表示,后续无byte,这个数到这里截止了)。
于是,合在一起为 1010 1100 0000 0010;
PB将 key编码成下面的结构:
X YYYY ZZZ
其中:最高位X表示是否还有后续的byte来编码数字别名;YYYY用于编码别名,定义了多于16个属性,则需要用到额外的byte,所以出现频率高的字段应当取1-16的别名);ZZZ表示这个字段的类型,PB支持的属性的对应规则如下表:
3.2具体实例分析
如下图所示,针对上述定义的proto文件及序列化后的字节流进行分析
byte[0]: 10 0 0001 010 别名1,类型repeated
byte[1]: 14 一个对象所占字节数
byte[2]: 8 0 0001 000 missionId
byte[3]: 16 0 0010 000 missionUserId
byte[4]: 24 0 0011 000 status
byte[5]: 32 0 0100 000 finishedTime
PB具有跨平台、解析速度快、序列化数据体积小、扩展性高、使用简单的特点。但是我们也可以看到,相比于XML,PB的数据,并不是自然可读的;同时它生成的代码不是纯pojo,对于代码有一定的侵入性。例如pb不支持像Map<Long, 0bject>,其中Object会出现多种不确定的类型,这样就无法通过pb序列化。从上述分析的数据可以看出,protobuf采用的k-v存储结构,并且采用变长的字节编码格式,所以从空间效率比较高。
相关推荐
Java protobuf框架使用向导ProtoBuf,全称是Protocol Buffers, 它是谷歌内部用的一种高效的、可扩展的对结构化数据进行编码的格式规范。谷歌自己内部很多程序之间的通信协议都用了ProtoBuf
ProtoBuf,全称是Protocol Buffers, 它是中软卓越内部用的一种高效的、可扩展的对结构化数据进行编码的格式规范。中软卓越自己内部很多程序之间的通信协议都用了ProtoBuf...该文档主要介绍了Java_protobuf框架的使用。
使用VertX测试协议缓冲区[JAVA] Vert.x是用于在JVM上构建响应式应用程序的工具包。 协议缓冲区是一种与语言无关,与平台无关的可扩展机制,用于序列化结构化数据。 该示例部署了两个顶点,它们之间传递了一个简单...
Java-Redisson-ProtoBufCodec
编码csv到protobuf npm install csv-protobuf-stream 用法 var csvProtobuf = require ( 'csv-protobuf-stream' ) ; var split = require ( 'binary-split' ) ; var encoder = csvProtobuf ( ) ; fs . ...
Parquet具有直接与Protobuf对象一起使用的模块,但是在为其他读取器(如Hive)编写数据时,这并非总是一个好的选择。 原因是Parquet和Protobuf使用相同的架构定义。 两者都支持必需的,可选的和重复的数据字段,并...
该项目的主要目的是展示如何使用公开Protobuf编码数据的终结点。 检查类ProducerRestTemplate以查看实现。 使用的框架和库 Spring Boot版本2.1.8-用于公开Protobuf对象以及JSON的RESFull端点,也用于依赖注入和所有...
[1]性能优势在很大程度上取决于用例和消息格式,但与Protobuf-Java 3.9.1 ,大多数常见用例在编码和解码速度方面的性能提升大约是 2 倍。 有关更多信息,请参阅 部分。 运行时库 您可以在 Maven Central 上的以下...
约会NIO高效并发框架——Netty,需要用到Java的基础知识(多线程,网络编程,IO,设计模式尤其是代理模式),介绍了Netty的高级架构设计和核心模块组件,Google上的Protobuf作为编码解码的数据存储格式,Netty编码器...
14_Protobuf完整实例详解 15_Protobuf集成Netty与多协议消息传 递 16_Protobuf多协议消息支援与工程最佳实践 17_Protobuf使用最佳实践与Apache Thrift介绍 18_Apache Thrift应用详解与实例剖析 19_Apache Thrift原理...
此步骤允许从使用 Google Protocol Buffers 编码的对象访问独立字段。 截图 以下是通过 Apache Kafka 传输的 Protocol Buffers 消息的实时解码示例: 安装 从下载pentaho-protobuf-decode Zip 存档。 将下载的存档...
17_Protobuf使用最佳实践与Apache Thrift介绍 18_Apache Thrift应用详解与实例剖析 19_Apache Thrift原理与架构解析 20_通过Apache Thrift实现Java与Python的RPC调用 21_gRPC深入详解 22_gRPC实践 23_Gradle Wrapper...
第17讲:Protobuf使用最佳实践与Apache Thrift介绍 第18讲:Apache Thrift应用详解与实例剖析 第19讲:Apache Thrift原理与架构解析 第20讲:通过Apache Thrift实现Java与Python的RPC调用 第21讲:gRPC深入详解 ...
净值 jdk bio,nio,aio各种使用案例,深入理解netty,结合源码以及文章分析: jdk原生nio的缓冲区使用 ...使用netty自带的编码解码器编写一个聊天室 在9的基础上加入私聊功能 在10的基础上加入pr
有限的兼容protobuf的语法规则 和 编码规则。包括protobuf2.0和3.0的编码规则。 实现proto结构的序列化、反序列化功能。 代码生成工具,需要boost库支持(主要用了spirit库做文本解析),本人用的是boost.1.64.0。 ...
有限的兼容protobuf的语法规则 和 编码规则。包括protobuf2.0和3.0的编码规则。 实现proto结构的序列化、反序列化功能。 代码生成工具,需要boost库支持(主要用了spirit库做文本解析),本人用的是boost.1.64.0。 ...
锐捷java笔试题 软件复用——谈复用解决方案 长连接心跳机制 ######使用netty来达到实现Client与Server的长...与其他的编码协议如xml,json相比,protobuf有着更好的传输效率和压缩比率。原生的protobuf包括两部分内容
要将新的或已修改的模式编译为Python存根,请运行./build_stubs.sh ,它使用与Protobuf一起使用。 要安装buf ,请按照的说明进行操作。使用Syft-Proto作为依赖项Python 可以通过pip install syft-proto : pip ...
格式化您的C系列代码 该插件使用以特定的编码样式格式化代码。 当前支持以下语言: C C ++ 目标C JavaScript Java打字稿原虫屏幕截图要求clang-format命令( 3.4或更高版本),捆绑在Clang附加工具中 (强烈推荐) ...
Hbase是Apache的NoSQL分布式可扩展Hadoop...Thrift网关和支持XML,Protobuf和二进制数据编码选项的REST-ful Web服务 可扩展的基于Jruby的(JIRB)Shell 支持通过Hadoop指标子系统将指标导出到文件或Ganglia;或通过JMX