Created
September 24, 2011 17:35
-
-
Save zhaoyao/1239611 to your computer and use it in GitHub Desktop.
Variable Byte Code Algorithm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.nio.ByteBuffer; | |
import java.util.*; | |
import static java.lang.Math.log; | |
/** | |
* User: zhaoyao | |
* Date: 11-9-24 | |
* Time: PM10:48 | |
*/ | |
public class VariableByteCode { | |
private static byte[] encodeNumber(int n) { | |
if (n == 0) { | |
return new byte[]{0}; | |
} | |
int i = (int) (log(n) / log(128)) + 1; | |
byte[] rv = new byte[i]; | |
int j = i - 1; | |
do { | |
rv[j--] = (byte) (n % 128); | |
n /= 128; | |
} while (j >= 0); | |
rv[i - 1] += 128; | |
return rv; | |
} | |
public static byte[] encode(List<Integer> numbers) { | |
ByteBuffer buf = ByteBuffer.allocate(numbers.size() * (Integer.SIZE / Byte.SIZE)); | |
for (Integer number : numbers) { | |
buf.put(encodeNumber(number)); | |
} | |
buf.flip(); | |
byte[] rv = new byte[buf.limit()]; | |
buf.get(rv); | |
return rv; | |
} | |
public static List<Integer> decode(byte[] byteStream) { | |
List<Integer> numbers = new ArrayList<Integer>(); | |
int n = 0; | |
for (byte b : byteStream) { | |
if ((b & 0xff) < 128) { | |
n = 128 * n + b; | |
} else { | |
int num = (128 * n + ((b - 128) & 0xff)); | |
numbers.add(num); | |
n = 0; | |
} | |
} | |
return numbers; | |
} | |
/** | |
* 对于已经排序好的数字序列,不再对原始值进行编码,而是对与前一个值的差值进行编码 | |
* <p/> | |
* [ 1, 2, 3, 4, 5, 6, 7 ] | |
* --> [1, 1, 1, 1, 1, 1, 1]f | |
* | |
* @param numbers | |
* @return | |
*/ | |
public static byte[] encodeInterpolate(List<Integer> numbers) { | |
ByteBuffer buf = ByteBuffer.allocate(numbers.size() * (Integer.SIZE / Byte.SIZE)); | |
int last = -1; | |
for (int i = 0; i < numbers.size(); i++) { | |
Integer num = numbers.get(i); | |
if (i == 0) { | |
buf.put(encodeNumber(num)); | |
} else { | |
buf.put(encodeNumber(num - last)); | |
} | |
last = num; | |
} | |
for (Integer number : numbers) { | |
buf.put(encodeNumber(number)); | |
} | |
buf.flip(); | |
byte[] rv = new byte[buf.limit()]; | |
buf.get(rv); | |
return rv; | |
} | |
public static List<Integer> decodeInterpolate(byte[] byteStream) { | |
List<Integer> numbers = new ArrayList<Integer>(); | |
int n = 0; | |
int last = -1; | |
boolean notFirst = false; | |
for (byte b : byteStream) { | |
if ((b & 0xff) < 128) { | |
n = 128 * n + b; | |
} else { | |
int num; | |
if (notFirst) { | |
num = last + (128 * n + ((b - 128) & 0xff)); | |
} else { | |
num = 128 * n + ((b - 128) & 0xff); | |
notFirst = true; | |
} | |
last = num; | |
numbers.add(num); | |
n = 0; | |
} | |
} | |
return numbers; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Greetings, there is a bug in Decode(). You don't handle the case where the encoded number is 0.
//need to add this if (b == 0 && n == 0) { numbers.add(0); } else if ((b & 0xff) < 128) {