前言

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 范例 - 字节处理的更多相关文章

  1. 聊聊Java的字节码

    本文为作者原创,转载请注明出处(http://www.cnblogs.com/mar-q/)by 负赑屃 巴山楚水凄凉地,二十三年弃置身.怀旧空吟闻笛赋,到乡翻似烂柯人.沉舟侧畔千帆过,病树前头万木春 ...

  2. 【java虚拟机系列】从java虚拟机字节码执行引擎的执行过程来彻底理解java的多态性

    我们知道面向对象语言的三大特点之一就是多态性,而java作为一种面向对象的语言,自然也满足多态性,我们也知道java中的多态包括重载与重写,我们也知道在C++中动态多态是通过虚函数来实现的,而虚函数是 ...

  3. Java 动态字节码技术

    对 Debug 的好奇 初学 Java 时,我对 IDEA 的 Debug 非常好奇,不止是它能查看断点的上下文环境,更神奇的是我可以在断点处使用它的 Evaluate 功能直接执行某些命令,进行一些 ...

  4. java虚拟机字节码执行引擎

    定义 java虚拟机字节码执行引擎是jvm最核心的组成部分之一,它做的事情很简单:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果.在不同的虚拟机实现里,执行引擎在执行java代码 ...

  5. Java中字节与对象之间的转换

    近期公司里面用到了消息队列,而正如我们知道的是消息队列之间的是通过二进制形式的.以下就分享一下java中字节与对象之间的转换. 主要是用到了ByteArrayOutputStream和ObjectOu ...

  6. Java IO: 字节和字符数组

    原文链接  作者: Jakob Jenkov   译者:homesick 内容列表 从InputStream或者Reader中读入数组 从OutputStream或者Writer中写数组 在java中 ...

  7. java class 字节码

    java class 字节码 协议: class文件 魔数(Magic):4byte -> 0xCAFEBABE 类似2f3f 版本(Version):4Byte -> 0x0000003 ...

  8. 小师妹学JVM之:java的字节码byte code简介

    目录 简介 Byte Code的作用 查看Byte Code字节码 java Byte Code是怎么工作的 总结 简介 Byte Code也叫做字节码,是连接java源代码和JVM的桥梁,源代码编译 ...

  9. 使用java动态字节码技术简单实现arthas的trace功能。

    参考资料 ASM 系列详细教程 编译时,找不到asm依赖 用过[Arthas]的都知道,Arthas是alibaba开源的一个非常强大的Java诊断工具. 不管是线上还是线下,我们都可以用Arthas ...

随机推荐

  1. 五、secureCRT远程连接工具的使用

    1.secureCRT实现远程传输文件到服务器机器 alt+p ,进入sftp模式,输入命令:put 文件所在的本机位置

  2. Linux驱动之输入子系统简析

    输入子系统由驱动层.输入子系统核心.事件处理层三部分组成.一个输入事件,如鼠标移动.键盘按下等通过Driver->Inputcore->Event handler->userspac ...

  3. Linux驱动之按键驱动编写(中断方式)

    在Linux驱动之按键驱动编写(查询方式)已经写了一个查询方式的按键驱动,但是查询方式太占用CPU,接下来利用中断方式编写一个驱动程序,使得CPU占有率降低,在按键空闲时调用read系统调用的进程可以 ...

  4. permissions required by Vibrator.vibrate: android.permission.VIBRATE

    <!-- 静止休眠 --><uses-permission android:name="android.permission.WAKE_LOCK" />&l ...

  5. DSP builder安装指南(以9.1为例) 转自http://www.cnblogs.com/sleepy/archive/2011/06/28/2092362.html

    DSP Builder在算法友好的开发环境中帮助设计人员生成DSP设计硬件表征,从而缩短了DSP设计周期.已有的MATLAB函数和Simulink模块可以和Altera DSP Builder模块以及 ...

  6. SQL SERVER占用CPU过高优化

    操作系统是Windows2008R2 ,数据库是SQL2014 64位. 近阶段服务器出现过几次死机,管理员反馈机器内存使用率100%导致机器卡死.于是做了个监测服务器的软件实时记录CPU数据,几日观 ...

  7. kaldi实例脚本运行

    Getting started, and prerequisites. rm/s5/run.sh Data preparation 如果有GridEngine, train_cmd="que ...

  8. 【洛谷4770】 [NOI2018]你的名字(SAM,线段树合并)

    传送门 洛谷 Solution 做过的比较玄学的后缀自动机. 果然就像\(Tham\)所讲,后缀自动机这种东西考场考了不可能做的出来的... 考虑如果\(l=1,r=|S|\)的怎么做? 直接建后缀自 ...

  9. asp.net对接拼多多

    asp.net对接拼多多视频地址:https://www.bilibili.com/video/av43512047/?p=7

  10. GET请求Referer限制绕过总结

    作者:Vulkey_Chen 原文来自:GET请求Referer限制绕过总结 前言 在做测试的时候会遇见这样几个漏洞场景: JSONP跨域劫持 反射XSS GET请求类型攻击 但是,在相对安全的情况下 ...