信息编码:基本整型(二)
ilder();
15 for (byte b : bArray) {
16 rtn.append(b & BYTEMASK).append(" ");
17 }
18 return rtn.toString();
19 }
20
21 // Warning: Untested preconditions (e.g., 0 <= size <=
8)
22 public static int encodeIntBigEndian(byte[] dst,
long val, int offset, int size) {
23 for (int i = 0; i < size; i++) {
24 dst[offset++] = (byte) (val >> ((size - i - 1) *
Byte.SIZE));
25 }
26 return offset;
27 }
28
29 // Warning: Untested preconditions (e.g., 0 <= size <=
8)
30 public static long decodeIntBigEndian(byte[]
val, int offset, int size) {
31 long rtn = 0;
32 for (int i = 0; i < size; i++) {
33 rtn = (rtn << Byte.SIZE) | ((long) val[offset + i] &
BYTEMASK);
34 }
35 return rtn;
36 }
37
38 public static void main(String[] args) {
39 byte[] message = new byte[BSIZE + SSIZE + ISIZE + LSIZE];
40 // Encode the fields in the target byte array
41 int offset = encodeIntBigEndian(message, byteva l, 0,
BSIZE);
42 offset = encodeIntBigEndian(message, shortVal, offset,
SSIZE);
43 offset = encodeIntBigEndian(message, intVal, offset,
ISIZE);
44 encodeIntBigEndian(message, longVal, offset, LSIZE);
45 System.out.println("Encoded message: " +
byteArrayToDecimalString(message));
46
47 // Decode several fields
48 long value = decodeIntBigEndian(message, BSIZE, SSIZE);
49 System.out.println("Decoded short = " + value);
50 value = decodeIntBigEndian(message, BSIZE + SSIZE +
ISIZE, LSIZE);
51 System.out.println("Decoded long = " + value);
52
53 // Demonstrate dangers of conversion
54 offset = 4;
55 value = decodeIntBigEndian(message, offset, BSIZE);
56 System.out.println("Decoded value (offset " +
offset + ", size " + BSIZE + ") = "
57 + value);
58 byte bVal = (byte) decodeIntBigEndian(message, offset,
BSIZE);
59 System.out.println("Same value as byte = " + bVal);
60 }
61
62 }
BruteForceCoding.java
1. 数据项编码:第1-4行
2. Java中的基本整数所占字节数:第6-9行
3. byteArrayToDecimalString():第13-19行
该方法把给定数组中的每个字节作为一个无符号十进制数打印出来。BYTEMASK的作用是防止在字节数值转换成int类型时,发生符号扩展(sign-extended),即转换成无符号整型。
4.encodeIntBigEndian():第22-27行
赋值语句的右边,首先将数值向右移动,以使我们需要的字节处于该数值的低8位中。然后,将移位后的数转换成byte型,并存入字节数组的适当位置。在转换过程中,除了低8位以外,其他位都将丢弃。这个过程将根据给定数值所占字节数迭代进行。该方法还将返回存入数值后字节数组中新的偏移位置,因此我们不必做额外的工作来跟踪偏移量。
5. decodeIntBigEndian():第30-36行
根据给定数组的字节大小进行迭代,通过每次迭代的左移操作,将所取得字节的值累积到一个long型整数中。
6. 示例方法:第38-60行
准备接收整数序列的数组:第39行
对每项进行编码:第40-44行
对byte,short,int以及long型整数进行编码,并按照前面描述的顺序存入字节数组。
打印编码后数组的内容:第45行
对编码字节数组中的某些字段进行解码:第47-51行
解码后输出的值应该与编码前的原始值相等。
转换问题:第53-59行
在字节数组偏移量为4的位置,该字节的十进制值是245,然而,当将其作为一个有符号字节读取时,其值则为-11(回忆有符号整数的二进制补码表示方法)。如果我们将返回值直接存入一个long型整数,它只是简单地变成这个long型整数的最后一个字节,值为245。如果将返回值放入一个字节型整数,其值则为-11。到底哪个值正确取决于你的应用程序。如果你从N个字节解码后希望得到一个有符号的数值,就必须将解码结果(长的结果)存入一个刚好占用N个字节的基本整型中。如果你希望得到一个无符号的数组,就必须将解码结果存入更长的基本整型中,该整型至少要占用N+1个字节。
注意,在encodeIntBigEndian() 和 decodeIntBigEndian()方法的开始部分,我们可能需要做一些前提条件检测,如0 ≤ size ≤ 8 和 dst ≠ null等。你能举出需要做的其他前期检测吗?
运行以上程序