1. 程式人生 > >關於資料序列化(4)自定義序列化的實現,支援常用集合框架

關於資料序列化(4)自定義序列化的實現,支援常用集合框架

下面的示例很好的揭示瞭如何實現自定義序列化的方法。
支援byte, byte[], boolean, boolean[], int, int[], long, long[] ,double ,double[], String, String[], 以及Enum, List,Map兩種包裝型別,以及實現了ISerilizable的實體類。
稍加改造就可以在專案中應用

/**
 * 分散式序列化介面
 * 除了基本型別 其餘資料需要分散式傳輸必須實現本介面
 * 注:實現本介面的類必須有無參建構函式!
 * @see SerializeTool#write(Object, java.io.DataOutputStream)
 * @see
SerializeTool#read(java.io.DataInputStream) */
public interface ISerilizable { public void writeTo(OutputStream out) throws IOException; public void readFrom(InputStream in) throws IOException; }
/**
 * 支援實現{@link ISerilizable}的類,<br>
 * 以及<b>byte,float,double,long</b>四種基本型別,<br>和
 * <b>Collection(list和set),map</b>三種集合框架,<br>和
 * <b>protobuf</b>.
 * <br>
 * TODO:迴圈因引用
 * @author
BAO * @see #readFile(String fileName) 建立關閉FileInputStream DataInputStream * @see #read(DataInputStream in) * @see #readObject(DataInputStream stream) throws Exception * */
public class SerializeTool { /** * 從流中讀取資料 * 只能順序讀 會自動進行型別轉換 * @return */ public static <T> T read
(DataInputStream stream) { try { return readObject(stream); } catch (Exception e) { LogCore.BASE.error("read err!", e); throw new SysException(e); } } /** * 從流中讀取資料 * 只能順序讀 會自動進行型別轉換 * @return */ @SuppressWarnings({ "unchecked", "rawtypes" }) private static <T> T readObject(DataInputStream stream) throws Exception { Object result = null; //型別碼 int wireFormat = stream.readInt(); //型別 int wireType = (wireFormat & ~ARRAY); //是陣列型別 boolean isArray = (wireFormat & ARRAY) == ARRAY; //陣列型別的長度 int arrayLen = 0; if(isArray) { arrayLen = stream.readInt(); } //空物件 if(wireType == NULL) { return null; } //BYTE if(wireType == BYTE) { if(isArray) { //result = stream.readRawBytes(arrayLen);//TODO 這個方法要調研一下! API應該提供此方法 byte[] values = new byte[arrayLen]; for(int i = 0; i < arrayLen; i++) { values[i] = stream.readByte(); } result = values; } else { result = stream.readByte(); } //BOOLEAN } else if(wireType == BOOLEAN) { if(isArray) { boolean[] values = new boolean[arrayLen]; for(int i = 0; i < arrayLen; i++) { values[i] = stream.readBoolean(); } result = values; } else { result = stream.readBoolean(); } //INT } else if(wireType == INT) { if(isArray) { int[] values = new int[arrayLen]; for(int i = 0; i < arrayLen; i++) { values[i] = stream.readInt(); } result = values; } else { result = stream.readInt(); } //LONG } else if(wireType == LONG) { if(isArray) { long[] values = new long[arrayLen]; for(int i = 0; i < arrayLen; i++) { values[i] = stream.readLong(); } result = values; } else { result = stream.readLong(); } //FLOAT } else if(wireType == FLOAT) { if(isArray) { float[] values = new float[arrayLen]; for(int i = 0; i < arrayLen; i++) { values[i] = stream.readFloat(); } result = values; } else { result = stream.readFloat(); } //DOUBLE } else if(wireType == DOUBLE) { if(isArray) { double[] values = new double[arrayLen]; for(int i = 0; i < arrayLen; i++) { values[i] = stream.readDouble(); } result = values; } else { result = stream.readDouble(); } //STRING } else if(wireType == STRING) { if(isArray) { String[] values = new String[arrayLen]; for(int i = 0; i < arrayLen; i++) { values[i] = stream.readUTF(); } result = values; } else { result = stream.readUTF(); } //ENUM } else if(wireType == ENUM) { //實際型別 String className = stream.readUTF(); String val = stream.readUTF(); //建立例項 Class cls = Class.forName(className); result = Enum.valueOf(cls, val); //COLLECTION LIST SET } else if(wireType == COLLECTION || wireType == LIST || wireType == SET) { //長度 int len = stream.readInt(); //型別 Collection list; if(wireType == LIST) list = new ArrayList<>(); else if(wireType == SET) list = new HashSet<>(); else list = new ArrayList<>(); //未知Collection的具體實現 暫時一律使用arrayList子類的實現 //填充資料 for(int i = 0; i < len; i++) { list.add(read(stream)); } result = list; //MAP } else if(wireType == MAP) { //長度 int len = stream.readInt(); //資料 Map map = new LinkedHashMap<>(); for(int i = 0; i < len; i++) { Object key = read(stream); Object val = read(stream); map.put(key, val); } result = map; //IDistributedSerilizable介面 } else if(wireType == DISTRIBUTED) { //實際型別 /*這種方式要提前生成常量池switch case(int) int id = stream.readInt(); ISerilizable seriable = org.gof.core.CommonSerializer.create(id); if(seriable == null) seriable = _commonFunc.apply(id); seriable.readFrom(this); result = seriable;*/ String className = stream.readUTF(); Class<?> cls = Class.forName(className); //建立例項並載入資料 Constructor<?> constructor = cls.getDeclaredConstructor(); constructor.setAccessible(true); ISerilizable seriable = (ISerilizable)constructor.newInstance(); seriable.readFrom(stream); result = seriable; //protobuf訊息 } else if(wireType == MSG) { //Object[] } else if(wireType == OBJECT && isArray) { Object[] values = new Object[arrayLen]; for(int i = 0; i < arrayLen; i++) { values[i] = read(stream); } result = values; //其餘一律不支援 } else { throw new SysException("發現無法被反序列化的型別: wireType={}, isArray={}", wireType, isArray); } //返回值 return (T) result; } /*write*/ public static <T> T deserilize(byte[] data){ ByteArrayInputStream in = new ByteArrayInputStream(data); DataInputStream stream = new DataInputStream(in); return read(stream); } /** * 連續讀取Object到list */ public static <T> List<T> deserilize2List(byte[] data){ return deserilize2List(data, new ArrayList<>()); } public static <T> List<T> deserilize2List(byte[] data, List<T> list){ try (ByteArrayInputStream in = new ByteArrayInputStream(data); DataInputStream stream = new DataInputStream(in)){ while(stream.available() > 0){ T t = read(stream); list.add(t); } return list; } catch (Exception e) { LogCore.BASE.error("read file err:{}", e); return null; } } public static byte[] serlize(Object value) throws IOException { try(ByteArrayOutputStream bout = new ByteArrayOutputStream(); DataOutputStream stream = new DataOutputStream(bout)) { writeObject(value, stream); return bout.toByteArray(); } catch (Exception e) { throw new SysException(e, "OutputStream寫入資料失敗。"); } } /** * 寫入資料到流中 * 僅支援 * byte byte[] boolean boolean[] int int[] long long[] * double double[] String String[] * Enum列舉 List、Map兩種包裝型別 * 以及實現了IDistributedSerilizable介面的類 * @param value * @throws IOException */ public static void write(Object value, DataOutputStream stream) { try { writeObject(value, stream); //不支援序列化化的錯誤 要對外匯報 } catch (Exception e) { throw new SysException(e, "OutputStream寫入資料失敗。"); } } /** * 寫入資料到流中 * 僅支援 * byte byte[] boolean boolean[] int int[] long long[] * double double[] String String[] * Enum列舉 List、Map兩種包裝型別 * 以及實現了IDistributedSerilizable介面的類 * @param value * @throws IOException */ static void writeObject(Object value, DataOutputStream stream) throws IOException { //空物件 if(value == null) { stream.writeInt(NULL); } //資料型別 Class<?> clazz = value.getClass(); //BYTE if(clazz == byte.class || clazz == Byte.class) { stream.writeInt(BYTE); stream.writeByte((byte)value); } else if(clazz == byte[].class) { byte[] array = (byte[])value; stream.writeInt(BYTE | ARRAY); stream.writeInt(array.length); stream.write(array); //BOOLEAN } else if(clazz == boolean.class || clazz == Boolean.class) { stream.writeInt(BOOLEAN); stream.writeBoolean((boolean)value); } else if(clazz == boolean[].class) { boolean[] array = (boolean[])value; stream.writeInt(BOOLEAN | ARRAY); stream.writeInt(array.length); for(int i = 0; i < array.length; i++) { stream.writeBoolean(array[i]); } //INT } else if(clazz == int.class || clazz == Integer.class) { stream.writeInt(INT); stream.writeInt((int)value); } else if(clazz == int[].class) { int[] array = (int[])value; stream.writeInt(INT | ARRAY); stream.writeInt(array.length); for(int i = 0; i < array.length; i++) { stream.writeInt(array[i]); } //LONG } else if(clazz == long.class || clazz == Long.class) { stream.writeInt(LONG); stream.writeLong((long)value); } else if(clazz == long[].class) { long[] array = (long[])value; stream.writeInt(LONG | ARRAY); stream.writeInt(array.length); for(int i = 0; i < array.length; i++) { stream.writeLong(array[i]); } //FLOAT } else if(clazz == float.class || clazz == Float.class) { stream.writeFloat(FLOAT); stream.writeFloat((float)value); } else if(clazz == float[].class) { float[] array = (float[])value; stream.writeInt(FLOAT | ARRAY); stream.writeInt(array.length); for(int i = 0; i < array.length; i++) { stream.writeFloat(array[i]); } //DOUBLE } else if(clazz == double.class || clazz == Double.class) { stream.writeInt(DOUBLE); stream.writeDouble((double)value); } else if(clazz == double[].class) { double[] array = (double[])value; stream.writeInt(DOUBLE | ARRAY); stream.writeInt(array.length); for(int i = 0; i < array.length; i++) { stream.writeDouble(array[i]); } //STRING } else if(clazz == String.class) { stream.writeInt(STRING); stream.writeUTF((String)value); } else if(clazz == String[].class) { String[] array = (String[])value; stream.writeInt(STRING | ARRAY); stream.writeInt(array.length); for(int i = 0; i < array.length; i++) { stream.writeUTF(array[i]); } //ENUM } else if(value instanceof Enum) { Enum<?> val = (Enum<?>) value; stream.writeInt(ENUM); stream.writeUTF(val.getClass().getName()); stream.writeUTF(val.name()); //COLLECTION LIST SET } else if(value instanceof Collection) { Collection<?> val = (Collection<?>) value; //判斷子型別 int type; if(value instanceof List) type = LIST; else if(value instanceof Set) type = SET; else type = COLLECTION; stream.writeInt(type); stream.writeInt(val.size()); for(Object o : val) { write(o, stream); } //MAP } else if(value instanceof Map) { Map<?,?> val = (Map<?,?>) value; stream.writeInt(MAP); stream.writeInt(val.size()); for(Entry<?, ?> e : val.entrySet()) { Object k = e.getKey(); Object v = e.getValue(); write(k, stream); write(v, stream); } //IDistributedSerilizable介面 } else if(value instanceof ISerilizable) { ISerilizable seriable = (ISerilizable)value; stream.writeInt(DISTRIBUTED); stream.writeInt(value.getClass().getName().hashCode()); seriable.writeTo(stream); //protobuf訊息 // } else if(value instanceof Message) { // Message msg = (Message)value; // byte[] bytes = msg.toByteArray(); // // stream.writeInt32NoTag(MSG); // stream.writeInt32NoTag(bytes.length); //訊息長度 不包括訊息型別 // stream.writeInt32NoTag(msg.getClass().getName().hashCode()); // stream.writeRawBytes(bytes); //陣列 } else if(value instanceof Object[]) { Object[] array = (Object[])value; stream.writeInt(OBJECT | ARRAY); stream.writeInt(array.length); for(Object o : array) { write(o, stream); } //其餘一律不支援 } else { throw new SysException("發現無法被序列化的型別:{}", clazz.getName()); } } }

思考:如何處理迴圈引用的問題?在json的序列化和protocol的序列化中的迴圈引用是如何處理的?