Java 范例 - 字节处理
前言
Java 编程中常会遇到需要进行字节处理的地方,本篇文章就来探讨编程中会遇到的字节处理问题。
字节序
字节序(endianness)是对于多字节数据来说的,它描述了多字节数据存储的顺序,分为大端字节序(big endian)和小端字节序(little endian)两种。
大端序即高位字节位于低地址,而小端字节序则与之相反。例如 4 字节的数据 0x01234567,其 大、小端字节序存储顺序如下。
Big Endian
address |0x100|0x101|0x102|0x103|
content |01 |23 |45 |67 |
Little Endian
address |0x100|0x101|0x102|0x103|
content |67 |45 |23 |01 |
为保证数据在不同设备进行传输时能被正确解析,规定了使用大端字节序作为网络字节序。
字节序转换
由于 Java 使用大端字节序在内存中进行数据存储,所以进行网络传输时不需要进行字节序转换。不过除了网络编程,还是有需要小端字节序的情况,下面就来讨论如何进行字节序的转换。
基本类型字节数
下表给出了 Java 八种基本类型的所占的字节数,可以看到里面六种类型都是多字节的,而这六种在转换时都是需要处理的。
| 类型 | 字节数 |
|---|---|
| byte | 1 |
| boolean | 1 |
| char | 2 |
| short | 2 |
| int | 4 |
| float | 4 |
| long | 8 |
| double | 8 |
这里需要强调一点,基本类型的数组形式虽是多字节的,但其字节序只和数组元素有关,而与数组元素的顺序无关。例如存在短整形数组 {0x0001, 0x0002} (Java 默认的大端字节序),则其小端字节序是 {0x0100, 0x0200} 。
字节缓冲区
字节缓冲区(ByteBuffer)常用于数据的字节级处理,可以利用静态方法 ByteBuffer allocate(int) 来申请一块固定大小的缓冲区,或者使用 ByteBuffer wrap(byte[]) 包装一个现有的字节数组。
字节缓冲区提供了 void order(ByteOrder) 方法来设置该字节缓冲区的字节序,提供了 asTypeBuffer() (其中 Type 为多字节的基本类型)来将字节缓冲区作为其他基本类型缓冲区,以便于插入其他基本类型,利用这些特性便可实现基本类型的字节序转换。
基本类型及其数组的字节序转换
下面例子利用了字节缓冲区来进行整型的字节序转换,而只需将 asIntBuffer() 改成相应基本类型的 asTypeBuffer() 方法,就可以进行其它基本类型的字节序转换。
int data = 0x01020304;
ByteBuffer buf = ByteBuffer.allocate(Integer.BYTES);
buf.asIntBuffer().put(data);
// [1, 2, 3, 4]
System.out.println(Arrays.toString(buf.array()));
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.asIntBuffer().put(data);
// [4, 3, 2, 1]
System.out.println(Arrays.toString(buf.array()));
对于基本类型的数组,只需将 data 数据改成数组即可,如下面给出的例子。
int[] data = new int[]{0x01020304, 0x05060708};
ByteBuffer buf = ByteBuffer.allocate(Integer.BYTES * data.length);
buf.asIntBuffer().put(data);
// [1, 2, 3, 4, 5, 6, 7, 8]
System.out.println(Arrays.toString(buf.array()));
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.asIntBuffer().put(data);
// [4, 3, 2, 1, 8, 7, 6, 5]
System.out.println(Arrays.toString(buf.array()));
字符串的字节序转换
Java 中字符类型使用 Unicode 字符集,所以占用两个字节,而字符串只需要将其转成字符数组即可进行字节序转换。
char[] data = new String("example").toCharArray();
ByteBuffer buf = ByteBuffer.allocate(Character.BYTES * data.length);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.asCharBuffer().put(data);
字符串编码与字节数组
编程中通常需要将字符串转字节数组,而这就涉及到字符串编解码,但 Java 提供了很便捷的方式来进行转换,所以无需关心如何字符串编解码。
byte[] buf = new String("example").getBytes(); // use platform's default charset
注意上面使用了平台的默认的字符集(可利用 Charset.defaultCharset() 获取平台默认字符集)进行解码,而不是上面提到的 Unicode 字符集,但可以如下面例子一样指定字符集。
byte[] buf = new String("example").getBytes("UTF-8"); // use specify charset 'UTF-8'
Java 范例 - 字节处理的更多相关文章
- 聊聊Java的字节码
本文为作者原创,转载请注明出处(http://www.cnblogs.com/mar-q/)by 负赑屃 巴山楚水凄凉地,二十三年弃置身.怀旧空吟闻笛赋,到乡翻似烂柯人.沉舟侧畔千帆过,病树前头万木春 ...
- 【java虚拟机系列】从java虚拟机字节码执行引擎的执行过程来彻底理解java的多态性
我们知道面向对象语言的三大特点之一就是多态性,而java作为一种面向对象的语言,自然也满足多态性,我们也知道java中的多态包括重载与重写,我们也知道在C++中动态多态是通过虚函数来实现的,而虚函数是 ...
- Java 动态字节码技术
对 Debug 的好奇 初学 Java 时,我对 IDEA 的 Debug 非常好奇,不止是它能查看断点的上下文环境,更神奇的是我可以在断点处使用它的 Evaluate 功能直接执行某些命令,进行一些 ...
- java虚拟机字节码执行引擎
定义 java虚拟机字节码执行引擎是jvm最核心的组成部分之一,它做的事情很简单:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果.在不同的虚拟机实现里,执行引擎在执行java代码 ...
- Java中字节与对象之间的转换
近期公司里面用到了消息队列,而正如我们知道的是消息队列之间的是通过二进制形式的.以下就分享一下java中字节与对象之间的转换. 主要是用到了ByteArrayOutputStream和ObjectOu ...
- Java IO: 字节和字符数组
原文链接 作者: Jakob Jenkov 译者:homesick 内容列表 从InputStream或者Reader中读入数组 从OutputStream或者Writer中写数组 在java中 ...
- java class 字节码
java class 字节码 协议: class文件 魔数(Magic):4byte -> 0xCAFEBABE 类似2f3f 版本(Version):4Byte -> 0x0000003 ...
- 小师妹学JVM之:java的字节码byte code简介
目录 简介 Byte Code的作用 查看Byte Code字节码 java Byte Code是怎么工作的 总结 简介 Byte Code也叫做字节码,是连接java源代码和JVM的桥梁,源代码编译 ...
- 使用java动态字节码技术简单实现arthas的trace功能。
参考资料 ASM 系列详细教程 编译时,找不到asm依赖 用过[Arthas]的都知道,Arthas是alibaba开源的一个非常强大的Java诊断工具. 不管是线上还是线下,我们都可以用Arthas ...
随机推荐
- Js学习(3) 数组
数组本质: 本质上数组是特殊的对象,因此,数组中可以放入任何类型的数据,对象,数组,函数都行 它的特殊性在于键名是按次序排列好的整数 从0开始,是固定的,不用指定键名 如果数组中的元素仍是数组,则为多 ...
- linux 下安装arm-linux-gnueabi交叉编译器
1,开发平台 虚拟机:vm12 系统:ubuntu14.04 LTS 32位 2.准备ARM交叉编译工具包 编译uboot和linux kernel都需要ARM交叉工具链支持,这里使用Linaro提 ...
- jenkins源码管理git分支参数化
多个分支来回切换构建时,每次都需要去很多个job里面改分支名称,比较费时,分支参数化后可以只改一处就ok啦 步骤: 1.进入系统管理--系统设置 2.勾选全局变量,然后输入分支变量名和对应的分支名称 ...
- [转载] ul li css 做横向菜单
原文地址: http://www.cnblogs.com/amylis_chen/archive/2011/09/24/2188398.html 第一步:建立一个无序列表 我们先建立一个无序列表,来建 ...
- 201771010142 张燕《面向对象程序设计(java)》第三周学习总结
实验三 Java基本程序设计(2) 实验时间 2018-9-13 1.实验目的与要求 (1)进一步掌握Eclipse集成开发环境下java程序开发基本步骤: (2)熟悉PTA平台线上测试环境: (3) ...
- Kali proxychains
1.什么是proxychains 在linux系统中有很多软件是不支持代理的,但是proxychains 却可以让不支持代理的软件 也能走代理通道,支持HTTP,HTTPS,SOCKS4,SOCKS5 ...
- 2019.02.11 bzoj4818: [Sdoi2017]序列计数(矩阵快速幂优化dp)
传送门 题意简述:问有多少长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数,且其中至少有一个数是质数,答案对201704082017040820170408取模(n≤1e9, ...
- LOJ-10102(求A到B之间的割点)
题目链接:传送门 思路:求A到B之间必要的中间节点 条件:(1)只有一条路径经过中间节点:(low[B]>=num[u]&&num[v]<=num[B],没有从B到u的路径 ...
- Qt中的CSS配置(QDarkStyleSheet)
QDarkStylesheet gihub地址 https://github.com/ColinDuquesnoy/QDarkStyleSheet
- Linux 线程编程1.0
在编译多线程程序的时候,需要连接libpthread文件: gcc pthread.c -o pthread -lpthread: 所有线程一律平等,没有父子关系,线程属于进程. 创建线程用 p ...