前言

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. Python开发——函数【Python内建函数】

  2. Spring源码-循环依赖源码解读

    Spring源码-循环依赖源码解读 笔者最近无论是看书还是从网上找资料,都没发现对Spring源码是怎么解决循环依赖这一问题的详解,大家都是解释了Spring解决循环依赖的想法(有的解释也不准确,在& ...

  3. 统计百分比的一个SQL脚本

    统计一个表中一个百分比的SQL脚本,不过这个是个万分比,这个数据类型要调一调 ),) declare @num3 decimal,@num4 decimal declare @percent deci ...

  4. SimpleDateFormat的parse(String str)方法的用法

    SimpleDateFormate 中的parse 方法可以将string类型的字符串转换成特定的date的特定类型.

  5. python之os库

    python之os库 os.name 判断现在正在实用的平台,Windows 返回 'nt'; Linux 返回'posix' >>> os.name 'nt' os.getcwd( ...

  6. ROM、RAM、DRAM、SRAM和FLASH、PSRAM

    1.ROM和RAM指的都是半导体存储器,ROM是Read Only Memory的缩写,RAM是Random Access Memory的缩写.ROM在系统停止供电的时候仍然可以保持数据,而RAM通常 ...

  7. 11g统计信息自动收集任务

    1.查看统计信息自动收集任务的开启情况. select client_name,status from dba_autotask_client; 2.查看自动收集任务各个窗口的开启情况. col op ...

  8. 装Office时,安装程序找不到Office.zh-cn\OfficeMUI问题

    运行Office 2007安装程序,没想到安装并不顺利,竟然在开始安装时就提示:"找不到Office.zh-cn\OfficeMUI.xml",而文件却是完整存在的,怎么回事? 原 ...

  9. ZKWeb网页框架1.9正式发布

    1.9.0更新的内容有 更新项目工具 更好的支持Linux 添加工具函数 Exception.ToDetailedString (获取例外的详细信息) Exception.ToSummaryStrin ...

  10. while循环 格式化输出 密码本 编码的初识

    第二天课程整理 while 循环 why : while ' 循环' 的意思 what : while 无限循环 how : 1.基本结构 while + 条件 循环的代码 初识循环 while tr ...