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 ...
随机推荐
- AJAX心得
持续补充... AJAX的核心是异步对象XMLHttpRequest对象,一个具有程序接口的JavaScript对象,能够使用超文本传输协议(HTTP)链接一个服务器. 这是一段标准的AJAX执行代码 ...
- [Python] 怎么把HTML的报告转换为图片,利用无头浏览器
How to convert HTML Report to picture format in Email? So that we can see the automation report also ...
- hibernate的Could not execute JDBC batch update错误原因及处理
http://blog.csdn.net/derpvailzhangfan/article/details/2332795\ 上述问题: 一设置关联 二包含关键字 三 映射文件设置 catalog=“ ...
- ios 学习路线总结
学习方法 面对有难度的功能,不要忙着拒绝,而是挑战一下,学习更多知识. 尽量独立解决问题,而不是在遇到问题的第一想法是找人. 多学习别人开源的第三方库,能够开源的库一定有值得学习的地方,多去看别的大神 ...
- 源码管理工具Git-客户端GitBash常用命令
1.配置用户名和邮箱地址(第一次启动程序时配置,以后使用不用配置)git config --global user.name "dolen"git config --global ...
- 20155339 Exp9 Web安全基础
Exp9 Web安全基础 基础问题回答 (1)SQL注入攻击原理,如何防御 原理:它是利用现有应用程序,将恶意的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入恶意SQL语句得到 ...
- Android studio提速配置
1. C:\Program Files\Android\Android Studio\bin studio64.exe.vmoptions 2.创建 gradle.properties 配置文件
- No趴笨小分队
这星期完成了小组的取名这一项重大的活动. 正所谓“名字是一个好开头”,取这个名义有以下的意义: 希望之后的学习以及工作能一帆风顺: 祝福各位小组成员之后的路能顺顺利利: 希望能在组员磨合的过程中可以愉 ...
- 27、通过visual s'tudio 验证 SOCKET编程:搭建一个TCP服务器
本文就是在windows下进行socket编程,搭建一个TCP客户端. 在visual studio下编程,首先在windows下进行初始化(这点在linux下是不需要的): /* 初始化 Winso ...
- redis知识点杂记
最近梳理了一下redis的基本知识.本文会从redis的简单使用.redis的数据类型.redis持久化三个方面做简单阐述和总结. 一.Redis基本操作 1.key的规则 不能使用\n空格.其他都可 ...