阅读更多
当前是个人把java的Output和Input的翻译成了AS3版本,虽然没什么技术含量,但是还是很有帮助,经过长时间使用,基本确保和java之间的通信没有任何问题。
package yxcq.kryo
{
import flash.utils.ByteArray;
import yxcq.utils.math.Long;
public class Input
{
protected var buffer:ByteArray;
public function Input(bytes:ByteArray)
{
if(bytes != null){
this.buffer = bytes;
this.buffer.position = 0;
}
}
public function get bytesAvailable():int
{
return buffer.bytesAvailable;
}
public function setBytes(bytes:ByteArray):void
{
this.buffer = bytes;
this.buffer.position = 0;
}
protected function require(required:int):int
{
if(buffer.bytesAvailable>=required)
return buffer.bytesAvailable;
else
throw new Error();
}
public function read():int
{
if(buffer.bytesAvailable<1)
return -1;
return buffer.readUnsignedByte()&0xFF;
}
public function skip(count:int):void
{
this.buffer.position = this.buffer.position+count;
}
public function readByte():int
{
require(1);
return buffer.readByte();
}
public function readByteUnsigned():int
{
require(1);
return buffer.readUnsignedByte();
}
public function readBytes(length:int):ByteArray
{
var bytes:ByteArray = new ByteArray;
_readBytes(bytes,0,length);
return bytes;
}
protected function _readBytes(bytes:ByteArray,offset:int,length:int):void
{
buffer.readBytes(bytes,offset,length);
}
public function readInt():int{
require(4);
return (buffer.readUnsignedByte() & 0xFF) << 24 //
| (buffer.readUnsignedByte() & 0xFF) << 16 //
| (buffer.readUnsignedByte() & 0xFF) << 8 //
| buffer.readUnsignedByte() & 0xFF;
}
/** Reads a 1-5 byte int. It is guaranteed that a varible length encoding will be used. */
public function readVarInt (optimizePositive:Boolean):int {
if (require(1) < 5) return readInt_slow(optimizePositive);
var b:int = buffer.readUnsignedByte();
var result:int = b & 0x7F;
if ((b & 0x80) != 0) {
b = buffer.readUnsignedByte();
result |= (b & 0x7F) << 7;
if ((b & 0x80) != 0) {
b = buffer.readUnsignedByte();
result |= (b & 0x7F) << 14;
if ((b & 0x80) != 0) {
b = buffer.readUnsignedByte();
result |= (b & 0x7F) << 21;
if ((b & 0x80) != 0) {
b = buffer.readUnsignedByte();
result |= (b & 0x7F) << 28;
}
}
}
}
return optimizePositive ? result : ((result >>> 1) ^ -(result & 1));
}
private function readInt_slow (optimizePositive:Boolean):int {
// The buffer is guaranteed to have at least 1 byte.
var b:int = buffer.readUnsignedByte();
var result:int = b & 0x7F;
if ((b & 0x80) != 0) {
require(1);
b = buffer.readUnsignedByte();
result |= (b & 0x7F) << 7;
if ((b & 0x80) != 0) {
require(1);
b = buffer.readUnsignedByte();
result |= (b & 0x7F) << 14;
if ((b & 0x80) != 0) {
require(1);
b = buffer.readUnsignedByte();
result |= (b & 0x7F) << 21;
if ((b & 0x80) != 0) {
require(1);
b = buffer.readUnsignedByte();
result |= (b & 0x7F) << 28;
}
}
}
}
return optimizePositive ? result : ((result >>> 1) ^ -(result & 1));
}
protected var chars:ByteArray = new ByteArray;
public function readString():String
{
var available:int = require(1);
var b:int = buffer.readUnsignedByte();
if((b&0x80) == 0)return readAscii();
var charCount:int = available>=5?readUtf8Length(b) : readUtf8Length_slow(b);
switch (charCount) {
case 0:
return null;
case 1:
return "";
}
charCount--;
chars.clear();
readUtf8(charCount);
var len:int = chars.position;
chars.position = 0;
return chars.readUTFBytes(len);
}
private function readUtf8Length (b:int):int {
var result:int = b & 0x3F; // Mask all but first 6 bits.
if ((b & 0x40) != 0) { // Bit 7 means another byte, bit 8 means UTF8.
b = buffer.readUnsignedByte();
result |= (b & 0x7F) << 6;
if ((b & 0x80) != 0) {
b = buffer.readUnsignedByte();
result |= (b & 0x7F) << 13;
if ((b & 0x80) != 0) {
b = buffer.readUnsignedByte();
result |= (b & 0x7F) << 20;
if ((b & 0x80) != 0) {
b = buffer.readUnsignedByte();
result |= (b & 0x7F) << 27;
}
}
}
}
return result;
}
private function readUtf8Length_slow (b:int):int {
var result:int = b & 0x3F; // Mask all but first 6 bits.
if ((b & 0x40) != 0) { // Bit 7 means another byte, bit 8 means UTF8.
require(1);
b = buffer.readUnsignedByte();
result |= (b & 0x7F) << 6;
if ((b & 0x80) != 0) {
require(1);
b = buffer.readUnsignedByte();
result |= (b & 0x7F) << 13;
if ((b & 0x80) != 0) {
require(1);
b = buffer.readUnsignedByte();
result |= (b & 0x7F) << 20;
if ((b & 0x80) != 0) {
require(1);
b = buffer.readUnsignedByte();
result |= (b & 0x7F) << 27;
}
}
}
}
return result;
}
private function readUtf8 (charCount:int):void {
// Try to read 7 bit ASCII chars.
var charIndex:int = 0;
var count:int = Math.min(require(1), charCount);
var b:int;
while (charIndex < count) {
b = buffer.readByte();
if (b < 0) {
this.buffer.position--;
break;
}
charIndex++;
chars.writeByte(b);
}
// If buffer didn't hold all chars or any were not ASCII, use slow path for remainder.
if (charIndex < charCount){
readUtf8_slow(charCount, charIndex);
}
}
private function readUtf8_slow (charCount:int, charIndex:int):void {
var utfstrlen:int = 0;
var position:int = buffer.position;
while (charIndex < charCount) {
var b:int = buffer.readByte() & 0x000000FF;
switch (b >> 4) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
chars.writeByte(b);
break;
case 12:
case 13:
chars.writeByte(b);
chars.writeByte(buffer.readByte());
break;
case 14:
chars.writeByte(b);
chars.writeByte(buffer.readByte());
chars.writeByte(buffer.readByte());
break;
}
charIndex++;
}
}
private function readAscii ():String {
var position:int = buffer.position;
var end:int = buffer.position;
var start:int = end -1;
var limit:int = buffer.length;
var b:int;
do {
if(end == limit){
buffer.position = position-1;
return readAscii_slow();
}
b = buffer.readUnsignedByte();
end++;
} while ((b & 0x00000080) == 0);
buffer[end - 1] &=0x0000007F; // Mask end of ascii bit.
buffer.position = position-1;
var value:String = (buffer as ByteArray).readMultiByte(end-start,'iso-8859-1');
buffer[end - 1] |= 0x00000080;
return value;
}
private function readAscii_slow ():String {
throw new Error("数据流中有不支持的字符串解析");
}
public function readFloat():Number
{
return buffer.readFloat();
}
public function readFloat2(precision:Number,optimizePositive:Boolean):Number
{
return Number(readInt_slow(optimizePositive))/precision;
}
public function readShort():int
{
return buffer.readShort();
}
public function readShortUnsigned():int
{
return buffer.readUnsignedShort();
}
public function readLong():Long
{
var h:int = buffer.readUnsignedByte()<<22;
h |= buffer.readUnsignedByte()<<16;
h |= buffer.readUnsignedByte()<<8;
h |= buffer.readUnsignedByte();
var l:int = buffer.readUnsignedByte()<<22;
l |= buffer.readUnsignedByte()<<16;
l |= buffer.readUnsignedByte()<<8;
l |= buffer.readUnsignedByte();
return new Long(h,l);
}
public function readVarLong (optimizePositive:Boolean):Long{
var b:int = buffer.readByte();
var low:int = b & 0x7F;
var high:int = 0;
if ((b & 0x80) != 0) {
b = buffer.readByte();
low |= (b & 0x7F) << 7;
if ((b & 0x80) != 0) {
b = buffer.readByte();
low |= (b & 0x7F) << 14;
if ((b & 0x80) != 0) {
b = buffer.readByte();
low |= (b & 0x7F) << 21;
if ((b & 0x80) != 0) {
b = buffer.readByte();
var temp:int = b&0x7F;
high = ((0 << temp) | (temp >>> 4) )|high;
low |= (temp << 28);
if ((b & 0x80) != 0) {
b = buffer.readByte();
high |= (b & 0x7F)<<3;
if ((b & 0x80) != 0) {
b = buffer.readByte();
high |= (b & 0x7F) << 10;
if ((b & 0x80) != 0) {
b = buffer.readByte();
high |= (b & 0x7F) << 17;
if ((b & 0x80) != 0) {
b = buffer.readByte();
high |= (b & 0x7F) << 24;
}
}
}
}
}
}
}
}
var result:Long = new Long(high,low);
if (!optimizePositive) result = result.rightShift(1,true).xor(result.and(1));
return result;
}
public function readBoolean():Boolean
{
return buffer.readUnsignedByte()==1;
}
public function readChar():int
{
return buffer.readUnsignedShort();
}
public function readDouble():Number
{
return buffer.readDouble();
}
/** Bulk input of an int array. */
public function readVarInts (length:int, optimizePositive:Boolean):Vector.{
var array:Vector. = new Vector.;
for (var i:int = 0; i < length; i++)
array[i] = readVarInt(optimizePositive);
return array;
}
public function readVarLongs (length:int, optimizePositive:Boolean):Vector.{
var array:Vector. = new Vector.;
for (var i:int = 0; i < length; i++)
array[i] = readVarLong(optimizePositive);
return array;
}
/** Bulk input of an int array. */
public function readInts (length:int) :Vector. {
var array:Vector. = new Vector.;
for (var i:int = 0; i < length; i++)
array[i] = readInt();
return array;
}
/** Bulk input of a long array. */
public function readLongs (length:int):Vector. {
var array:Vector. = new Vector.;
for (var i:int = 0; i < length; i++)
array[i] = readLong();
return array;
}
/** Bulk input of a float array. */
public function readFloats (length:int) :Vector. {
var array:Vector. = new Vector.;
for (var i:int = 0; i < length; i++)
array[i] = readFloat();
return array;
}
/** Bulk input of a short array. */
public function readShorts (length:int):Vector. {
var array:Vector. = new Vector.;
for (var i:int = 0; i < length; i++)
array[i] = readShort();
return array;
}
/** Bulk input of a char array. */
public function readChars (length:int):Vector. {
var array:Vector. = new Vector.;
for (var i:int = 0; i < length; i++)
array[i] = readChar();
return array;
}
/** Bulk input of a double array. */
public function readDoubles (length:int):Vector. {
var array:Vector. = new Vector.;
for (var i:int = 0; i < length; i++)
array[i] = readDouble();
return array;
}
}
}
package yxcq.kryo
{
import yxcq.utils.math.Long;
import flash.utils.ByteArray;
public class Output
{
protected var buffer:ByteArray = new ByteArray;
public function Output()
{
}
public function getBuffer():ByteArray
{
return buffer;
}
public function write(value:int):void
{
buffer.writeByte(value);
}
public function writeBytes(bytes:ByteArray,offset:int,length:int):void
{
buffer.writeBytes(bytes,offset,length);
}
public function writeByte(b:int):void
{
buffer.writeByte(b);
}
public function writeInt(value:int):void
{
buffer.writeInt(value);
}
public function writeVarInt(value:int,optimizePositive:Boolean):int
{
if(!optimizePositive) value = (value<<1)^(value>>31);
if(value>>>7 == 0){
buffer.writeByte(value&0xFF);
return 1;
}
if(value>>>14 == 0){
buffer.writeByte((value&0x7F | 0x80)&0xFF);
buffer.writeByte((value>>>7)&0xFF);
return 2;
}
if (value >>> 21 == 0) {
buffer.writeByte((value&0x7F | 0x80)&0xFF);
buffer.writeByte((value>>>7|0x80)&0xFF);
buffer.writeByte((value>>>14)&0xFF);
return 3;
}
if (value >>> 28 == 0) {
buffer.writeByte((value&0x7F | 0x80)&0xFF);
buffer.writeByte((value>>>7|0x80)&0xFF);
buffer.writeByte((value>>>14|0x80)&0xFF);
buffer.writeByte((value>>>21)&0xFF);
return 4;
}
buffer.writeByte((value&0x7F | 0x80)&0xFF);
buffer.writeByte((value>>>7|0x80)&0xFF);
buffer.writeByte((value>>>14|0x80)&0xFF);
buffer.writeByte((value>>>21|0x80)&0xFF);
buffer.writeByte((value>>>28)&0xFF);
return 5;
}
public function writeVarLong (value:Long, optimizePositive:Boolean):int{
if (!optimizePositive) value = value.leftShift(1).xor(value.rightShift(63));
if (value.rightShift(7,true).isZero()) {
buffer.writeByte(value.getLow());
return 1;
}
if (value.rightShift(14,true).isZero()) {
buffer.writeByte(value.and(0x7F).or(0x80).getLow());
buffer.writeByte(value.rightShift(7,true).getLow());
return 2;
}
if (value.rightShift(21,true).isZero()) {
buffer.writeByte(value.and(0x7F).or(0x80).getLow());
buffer.writeByte(value.rightShift(7,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(14,true).getLow());
return 3;
}
if (value.rightShift(28,true).isZero()) {
buffer.writeByte(value.and(0x7F).or(0x80).getLow());
buffer.writeByte(value.rightShift(7,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(14,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(21,true).getLow());
return 4;
}
if (value.rightShift(35,true).isZero()) {
buffer.writeByte(value.and(0x7F).or(0x80).getLow());
buffer.writeByte(value.rightShift(7,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(14,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(21,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(28,true).getLow());
return 5;
}
if (value.rightShift(42,true).isZero()) {
buffer.writeByte(value.and(0x7F).or(0x80).getLow());
buffer.writeByte(value.rightShift(7,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(14,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(21,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(28,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(35,true).getLow());
return 6;
}
if (value.rightShift(49,true).isZero()) {
buffer.writeByte(value.and(0x7F).or(0x80).getLow());
buffer.writeByte(value.rightShift(7,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(14,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(21,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(28,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(35,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(42,true).getLow());
return 7;
}
if (value.rightShift(56,true).isZero()) {
buffer.writeByte(value.and(0x7F).or(0x80).getLow());
buffer.writeByte(value.rightShift(7,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(14,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(21,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(28,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(35,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(42,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(49,true).getLow());
return 8;
}
buffer.writeByte(value.and(0x7F).or(0x80).getLow());
buffer.writeByte(value.rightShift(7,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(14,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(21,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(28,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(35,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(42,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(49,true).or(0x80).getLow());
buffer.writeByte(value.rightShift(56,true).getLow());
return 9;
}
public function writeString (value:String):void {
if (value == null) {
writeByte(0x80); // 0 means null, bit 8 means UTF8.
return;
}
var charCount:int = value.length;
if (charCount == 0) {
writeByte(1 | 0x80); // 1 means empty string, bit 8 means UTF8.
return;
}
// Detect ASCII. 检查是否ASCII
var ascii:Boolean = false;
if (charCount > 1 && charCount < 64) {
ascii = true;
for (var i:int = 0; i < charCount; i++) {
var c:int = value.charCodeAt(i);
if (c > 127) {
ascii = false;
break;
}
}
}
if (ascii) {
buffer.writeUTFBytes(value);
buffer[buffer.position - 1] |= 0x80;
} else {
writeUtf8Length(charCount + 1);
var charIndex:int = 0;
var position:int = buffer.position;
// Try to write 8 bit chars.
for (; charIndex < charCount; charIndex++) {
var c:int = value.charCodeAt(charIndex);
if (c > 127) break;
buffer.writeByte(c&0xFF);
position++;
}
buffer.position = position;
if (charIndex < charCount)
writeString_slow(value, charCount, charIndex);
}
}
/** Writes a string that is known to contain only ASCII characters. Non-ASCII strings passed to this method will be corrupted.
* Each byte is a 7 bit character with the remaining byte denoting if another character is available. This is slightly more
* efficient than {@link #writeString(String)}. The string can be read using {@link Input#readString()} or
* {@link Input#readStringBuilder()}.
* @param value May be null. */
public function writeAscii (value:String):void{
if (value == null) {
writeByte(0x80); // 0 means null, bit 8 means UTF8.
return;
}
var charCount:int = value.length;
switch (charCount) {
case 0:
writeByte(1 | 0x80); // 1 is string length + 1, bit 8 means UTF8.
return;
case 1:
writeByte(2 | 0x80); // 2 is string length + 1, bit 8 means UTF8.
writeByte(value.charCodeAt(0));
return;
}
buffer.writeUTF(value);
buffer[buffer.position - 1] |= 0x80; // Bit 8 means end of ASCII.
}
/** Writes the length of a string, which is a variable length encoded int except the first byte uses bit 8 to denote UTF8 and
* bit 7 to denote if another byte is present. */
private function writeUtf8Length (value:int):void {
if (value >>> 6 == 0) {
buffer.writeByte((value | 0x80)&0xFF); // Set bit 8.
} else if (value >>> 13 == 0) {
buffer.writeByte((value | 0x40 | 0x80)&0xFF); // Set bit 7 and 8.
buffer.writeByte((value >>> 6)&0xFF);
} else if (value >>> 20 == 0) {
buffer.writeByte((value | 0x40 | 0x80)&0xFF); // Set bit 7 and 8.
buffer.writeByte(((value >>> 6) | 0x80)&0xFF); // Set bit 8.
buffer.writeByte((value >>> 13)&0xFF);
} else if (value >>> 27 == 0) {
buffer.writeByte((value | 0x40 | 0x80)&0xFF); // Set bit 7 and 8.
buffer.writeByte(((value >>> 6) | 0x80)&0xFF); // Set bit 8.
buffer.writeByte(((value >>> 13) | 0x80)&0xFF); // Set bit 8.
buffer.writeByte((value >>> 20)&0xFF);
} else {
buffer.writeByte((value | 0x40 | 0x80)&0xFF); // Set bit 7 and 8.
buffer.writeByte(((value >>> 6) | 0x80)&0xFF); // Set bit 8.
buffer.writeByte(((value >>> 13) | 0x80)&0xFF); // Set bit 8.
buffer.writeByte(((value >>> 20) | 0x80)&0xFF); // Set bit 8.
buffer.writeByte((value >>> 27)&0xFF);
}
}
private function writeString_slow (value:String, charCount:int, charIndex:int):void {
for (; charIndex < charCount; charIndex++) {
var c:int = value.charCodeAt(charIndex);
if (c <= 0x007F) {
buffer.writeByte(c&0xFF);
} else if (c > 0x07FF) {
buffer.writeByte((0xE0 | c >> 12 & 0x0F)&0xFF);
buffer.writeByte((0x80 | c >> 6 & 0x3F)&0xFF);
buffer.writeByte((0x80 | c & 0x3F)&0xFF);
} else {
buffer.writeByte((0xC0 | c >> 6 & 0x1F)&0xFF);
buffer.writeByte((0x80 | c & 0x3F)&0xFF);
}
}
}
public function writeFloat(value:Number):void
{
this.buffer.writeFloat(value);
}
public function writeFloat2(value:Number,precision:Number,optimizePositive:Boolean):void
{
this.writeVarInt(value*precision,optimizePositive);
}
public function writeShort(value:int):void
{
this.buffer.writeShort(value);
}
public function writeLong(value:Long):void
{
this.buffer.writeByte(value.getHigh()>>>24);
this.buffer.writeByte(value.getHigh()>>>16);
this.buffer.writeByte(value.getHigh()>>>8);
this.buffer.writeByte(value.getHigh());
this.buffer.writeByte(value.getLow()>>>24);
this.buffer.writeByte(value.getLow()>>>16);
this.buffer.writeByte(value.getLow()>>>8);
this.buffer.writeByte(value.getLow());
}
public function writeBoolean(value:Boolean):void
{
this.buffer.writeBoolean(value);
}
public function writeChar(value:int):void
{
this.buffer.writeShort(value);
}
public function writeDouble(value:Number):void
{
this.buffer.writeDouble(value);
}
/** Bulk output of an int array. */
public function writeVarInts (object:Vector., optimizePositive:Boolean) :void {
for (var i:int = 0, n:int = object.length; i < n; i++)
writeVarInt(object[i], optimizePositive);
}
/** Bulk output of an int array. */
public function writeInts (object:Vector.) :void {
for (var i:int = 0, n:int = object.length; i < n; i++)
this.buffer.writeInt(object[i]);
}
public function writeVarLongs (object:Vector., optimizePositive:Boolean):void{
for (var i:int = 0, n:int = object.length; i < n; i++)
writeVarLong(object[i], optimizePositive);
}
/** Bulk output of an long array. */
public function writeLongs (object:Vector.) :void {
for (var i:int = 0, n:int = object.length; i < n; i++)
writeLong(object[i]);
}
/** Bulk output of a float array. */
public function writeFloats (object:Vector.) :void {
for (var i:int = 0, n:int = object.length; i < n; i++)
writeFloat(object[i]);
}
/** Bulk output of a short array. */
public function writeShorts (object:Vector.) :void {
for (var i:int = 0, n:int = object.length; i < n; i++)
writeShort(object[i]);
}
/** Bulk output of a char array. */
public function writeChars (object:Vector.) :void {
for (var i:int = 0, n:int = object.length; i < n; i++)
writeChar(object[i]);
}
/** Bulk output of a double array. */
public function writeDoubles (object:Vector.) :void {
for (var i:int = 0, n:int = object.length; i < n; i++)
writeDouble(object[i]);
}
}
}