前言

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. Ubuntu 18.04学习笔记

    命令行快捷键 https://blog.csdn.net/wanlhr/article/details/80926804 Ubuntu18.04使用vi命令修改文件并保存 vi /opt/teamvi ...

  2. js学习(4) 函数

    JavaScript有三种声明函数的方法 (1)function命令 function print(s) { console.log(s); } (2)函数表达式 1.var print = func ...

  3. 以太坊Inner Transaction合约内充值转账

  4. (转)Android四大组件——Activity跳转动画、淡出淡入、滑出滑入、自定义退出进入

    文章转自:http://blog.csdn.net/qq_30379689/article/details/52494270 Activity跳转动画.淡入淡出.滑入滑出.自定义退出进入 前言: 系统 ...

  5. 74.CocoaPods安装和使用教程

    CocoaPods安装和使用教程  Code4App 原创文章.转载请注明出处:http://code4app.com/article/cocoapods-install-usage 第一: Coco ...

  6. ABP框架系列之九:(Abp-Session-会话)

    Introduction ASP.NET Boilerplate provides IAbpSession interface to obtain current user and tenant wi ...

  7. 第41章:MongoDB-集群--Sharding(分片)

    ①Sharding分片概念 分片(sharding)是指将数据库拆分,将其分散在不同的机器上的过程.将数据分散到不同的机器上,不需要功能强大的服务器就可以存储更多的数据和处理更大的负载. 分片是每个分 ...

  8. [转]Ubuntu16.04下ralink rt3290驱动安装

    出处:https://askubuntu.com/questions/253632/how-do-i-get-a-ralink-rt3290-wireless-card-working 解决为问题:L ...

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

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

  10. CentOS 7安装新版RabbitMQ解决Erlang 19.3版本依赖

    通过yum等软件仓库都可以直接安装RabbitMQ,但版本一般都较为保守. RabbitMQ官网提供了新版的rpm包(http://www.rabbitmq.com/download.html),但是 ...