ByteOrder

预计阅读时间:3分钟

当对大于8位/字节/八位位组的固定大小值进行编码时,有两种标准方法:通过首先存储数字字节的低位部分(LITTLE字节),或通过先存储最高有效字节(BIG字节) ).

nativeOrder()表示主CPU使用的顺序. 本地顺序通常会稍快一些,因为处理器可以避免字节交换操作.

expect enum class ByteOrder {
    BIG_ENDIAN, LITTLE_ENDIAN;

    companion object {
        fun nativeOrder(): ByteOrder
    }
}

LITTLE Endian

小尾数是x86处理器和大多数ARM处理器的本机顺序. 这是最流行的CPU本机顺序.

  • 好处:对于较小的数字,您首先会获得最相关的信息,并且可以在不事先知道位宽的情况下以有意义的方式进行读取.
  • 缺点:无法自然地从左到右读取.

BIG Endian

大端,也称为网络端或摩托罗拉端. 这是网络协议最常用的字节序. 过去,某些CPU使用它作为本机字节序,包括Motorla,一些MIPS和ARM,PowerPC,SPARC等.

  • 优点:即使以十六进制表示,也可以从左至右自然读取.
  • 缺点:您需要事先知道数据的宽度,才能有意义地读取它.

Tools

Converting values between endians:

当然,您可以使用一个endian序列化视图或数据包中的值,然后使用另一个endian对其进行反序列化.

但是有更有效的方法. 对于ShortIntLong ,您具有:

  • java.lang.Short.reverseBytes(10.toShort()) - (16 bits, 2 octets) AA BB <-> BB AA
  • java.lang.Integer.reverseBytes(10) - (32 bits, 4 octets) AA BB CC DD <-> DD CC BB AA
  • java.lang.Long.reverseBytes(10L) - (64 bits, 8 octets) AA BB CC DD EE FF GG HH <-> HH GG FF EE DD CC BB AA

FloatDouble可以通过获取它们的位并从它们的位进行重构来反转:

  • Float.fromBits(java.lang.Integer.reverseBytes(10f.toBits())) - (32 bits, 4 octets)
  • Double.fromBits(java.lang.Long.reverseBytes(10.0.toBits())) - (64 bits, 8 octets)

对于浮点数(32位)(与Double相似,但指数和分数位递增),有一个符号(1位),指数(8位)和一个分数(23位): seeeeeeeefffffffffffffffffffffff -s = sign, e =指数,f =分数. 以八位字节为单位: seeeeeee-efffffff-ffffffff-ffffffff ,因此反转字节将产生非常奇怪的浮点值.

Extensions methods in pure Kotlin for byte-reversing integral types

使用JVM时,除了Byte之外,每个框式整数类型都提供一个reverseBytes方法(例如java.lang.Integer.reverseBytes ). 对于常见目标和其他Kotlin目标,可以使用以下扩展方法:

fun Short.reverseBytes(): Short {
	val v0 = ((this.toInt() ushr 0) and 0xFF)
	val v1 = ((this.toInt() ushr 8) and 0xFF)
	return ((v1 and 0xFF) or (v0 shl 8)).toShort()
}

fun Int.reverseBytes(): Int {
	val v0 = ((this ushr 0) and 0xFF)
	val v1 = ((this ushr 8) and 0xFF)
	val v2 = ((this ushr 16) and 0xFF)
	val v3 = ((this ushr 24) and 0xFF)
	return (v0 shl 24) or (v1 shl 16) or (v2 shl 8) or (v3 shl 0)
}

fun Long.reverseBytes(): Long {
	val v0 = (this ushr 0).toInt().reverseBytes().toLong() and 0xFFFFFFFFL
	val v1 = (this ushr 32).toInt().reverseBytes().toLong() and 0xFFFFFFFFL
	return (v0 shl 32) or (v1 shl 0)
}

by  ICOPY.SITE