package cn.jcenterhome.util; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.TreeMap; public class Serializer { private static final byte __Quote = 34; private static final byte __0 = 48; private static final byte __1 = 49; private static final byte __Colon = 58; private static final byte __Semicolon = 59; private static final byte __N = 78; private static final byte __U = 85; private static final byte __Slash = 92; private static final byte __a = 97; private static final byte __b = 98; private static final byte __d = 100; private static final byte __i = 105; private static final byte __s = 115; private static final byte __LeftB = 123; private static final byte __RightB = 125; private static final String __NAN = "NAN"; private static final String __INF = "INF"; private static final String __NINF = "-INF"; public static String serialize(Object obj) { return serialize(obj, JavaCenterHome.JCH_CHARSET); } @SuppressWarnings("unchecked") public static String serialize(Object obj, String charset) { ByteArrayOutputStream stream = new ByteArrayOutputStream(); serialize(stream, obj, charset); String result = null; try { result = stream.toString(charset); } catch (Exception e) { e.printStackTrace(); } return result; } @SuppressWarnings("unchecked") private static void serialize(ByteArrayOutputStream stream, Object obj, String charset) { if (obj == null) { writeNull(stream); } else if (obj instanceof Boolean) { writeBoolean(stream, ((Boolean) obj).booleanValue() ? __1 : __0); } else if ((obj instanceof Byte) || (obj instanceof Short) || (obj instanceof Integer)) { writeInteger(stream, getAsciiBytes(obj)); } else if (obj instanceof Long) { writeDouble(stream, getAsciiBytes(obj)); } else if (obj instanceof Float) { Float f = (Float) obj; obj = f.isNaN() ? __NAN : (!f.isInfinite() ? obj : (f.floatValue() > 0 ? __INF : __NINF)); writeDouble(stream, getAsciiBytes(obj)); } else if (obj instanceof Double) { Double d = (Double) obj; obj = d.isNaN() ? __NAN : (!d.isInfinite() ? obj : (d.doubleValue() > 0 ? __INF : __NINF)); writeDouble(stream, getAsciiBytes(obj)); } else if ((obj instanceof Character) || (obj instanceof String) || (obj instanceof StringBuffer)) { writeString(stream, getBytes(obj, charset)); } else if (obj instanceof Map) { writeMap(stream, (Map) obj, charset); } else if (obj instanceof List) { writeList(stream, (List) obj, charset); } else { System.out.println("Serializer.serialize: The DataType is invalid"); } } private static void writeNull(ByteArrayOutputStream stream) { stream.write(__N); stream.write(__Semicolon); } private static void writeBoolean(ByteArrayOutputStream stream, byte b) { stream.write(__b); stream.write(__Colon); stream.write(b); stream.write(__Semicolon); } private static void writeInteger(ByteArrayOutputStream stream, byte[] i) { stream.write(__i); stream.write(__Colon); stream.write(i, 0, i.length); stream.write(__Semicolon); } private static void writeDouble(ByteArrayOutputStream stream, byte[] d) { stream.write(__d); stream.write(__Colon); stream.write(d, 0, d.length); stream.write(__Semicolon); } private static void writeString(ByteArrayOutputStream stream, byte[] s) { byte[] slen = getAsciiBytes(new Integer(s.length)); stream.write(__s); stream.write(__Colon); stream.write(slen, 0, slen.length); stream.write(__Colon); stream.write(__Quote); stream.write(s, 0, s.length); stream.write(__Quote); stream.write(__Semicolon); } @SuppressWarnings("unchecked") private static void writeList(ByteArrayOutputStream stream, List a, String charset) { int len = a.size(); byte[] alen = getAsciiBytes(new Integer(len)); stream.write(__a); stream.write(__Colon); stream.write(alen, 0, alen.length); stream.write(__Colon); stream.write(__LeftB); for (int i = 0; i < len; i++) { writeInteger(stream, getAsciiBytes(new Integer(i))); serialize(stream, a.get(i), charset); } stream.write(__RightB); } @SuppressWarnings("unchecked") private static void writeMap(ByteArrayOutputStream stream, Map h, String charset) { int len = h.size(); byte[] hlen = getAsciiBytes(new Integer(len)); stream.write(__a); stream.write(__Colon); stream.write(hlen, 0, hlen.length); stream.write(__Colon); stream.write(__LeftB); for (Iterator keys = h.keySet().iterator(); keys.hasNext();) { Object key = keys.next(); if ((key instanceof Byte) || (key instanceof Short) || (key instanceof Integer)) { writeInteger(stream, getAsciiBytes(key)); } else if (key instanceof Boolean) { writeInteger(stream, new byte[] {((Boolean) key).booleanValue() ? __1 : __0}); } else { writeString(stream, getBytes(key, charset)); } serialize(stream, h.get(key), charset); } stream.write(__RightB); } private static byte[] getAsciiBytes(Object obj) { try { return obj.toString().getBytes("US-ASCII"); } catch (Exception e) { return null; } } private static byte[] getBytes(Object obj, String charset) { try { return obj.toString().getBytes(charset); } catch (Exception e) { return obj.toString().getBytes(); } } @SuppressWarnings("unchecked") public static Map unserialize(String targetString, boolean isTreeMap) { if (targetString == null || targetString.equals("")) { return new HashMap(); } Map resultMap = null; try { resultMap = (Map) Serializer.unserialize(targetString, isTreeMap ? 1 : 2); } catch (Exception e) { e.printStackTrace(); } return resultMap; } @SuppressWarnings("unchecked") public static List unserialize(String targetString) { if (targetString == null || targetString.equals("")) { return new ArrayList(); } List result = null; try { result = (List) Serializer.unserialize(targetString, 0); } catch (Exception e) { e.printStackTrace(); } return result; } public static Object unserialize(String ss, int state) { return unserialize(ss, JavaCenterHome.JCH_CHARSET, state); } @SuppressWarnings("unchecked") public static Object unserialize(String ss, String charset, int state) { ByteArrayInputStream stream = null; try { stream = new ByteArrayInputStream(ss.getBytes(charset)); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } Object result = unserialize(stream, charset, state); return result; } @SuppressWarnings("unchecked") private static Object unserialize(ByteArrayInputStream stream, String charset, int state) { switch (stream.read()) { case __N: return readNull(stream); case __b: return readBoolean(stream); case __i: return readInteger(stream); case __d: return readDouble(stream); case __s: return readString(stream, charset); case __U: return readUnicodeString(stream); case __a: return readArray(stream, charset, state); default: System.out.println("Serializer.unserialize: The DataType Is invalid,state=" + state); return null; } } private static String readNumber(ByteArrayInputStream stream) { StringBuffer sb = new StringBuffer(); int i = stream.read(); while ((i != __Semicolon) && (i != __Colon)) { sb.append((char) i); i = stream.read(); } return sb.toString(); } private static Object readNull(ByteArrayInputStream stream) { stream.skip(1); return null; } private static Boolean readBoolean(ByteArrayInputStream stream) { stream.skip(1); boolean b = stream.read() == __1; stream.skip(1); return b; } private static Number readInteger(ByteArrayInputStream stream) { stream.skip(1); String i = readNumber(stream); return Integer.parseInt(i); } private static Number readDouble(ByteArrayInputStream stream) { stream.skip(1); String d = readNumber(stream); if (d.equals(__NAN)) { return new Double(Double.NaN); } if (d.equals(__INF)) { return new Double(Double.POSITIVE_INFINITY); } if (d.equals(__NINF)) { return new Double(Double.NEGATIVE_INFINITY); } if ((d.indexOf('.') > 0) || (d.indexOf('e') > 0) || (d.indexOf('E') > 0)) { return new Double(d); } int len = d.length(); char c = d.charAt(0); if ((len < 19) || ((c == '-') && (len < 20))) { return new Long(d); } if ((len > 20) || ((c != '-') && (len > 19))) { return new Double(d); } try { return new Long(d); } catch (Exception e) { return new Double(d); } } private static String readString(ByteArrayInputStream stream, String charset) { stream.skip(1); int len = Integer.parseInt(readNumber(stream)); stream.skip(1); byte[] buf = new byte[len]; stream.read(buf, 0, len); stream.skip(2); try { return new String(buf, charset); } catch (Exception e) { return new String(buf); } } private static String readUnicodeString(ByteArrayInputStream stream) { stream.skip(1); int len = Integer.parseInt(readNumber(stream)); stream.skip(1); StringBuffer sb = new StringBuffer(len); int c; for (int i = 0; i < len; i++) { if ((c = stream.read()) == __Slash) { char[] chs = new char[4]; chs[0] = (char) stream.read(); chs[1] = (char) stream.read(); chs[2] = (char) stream.read(); chs[3] = (char) stream.read(); sb.append((char) (Integer.parseInt(new String(chs), 16))); } else { sb.append((char) c); } } stream.skip(2); return sb.toString(); } @SuppressWarnings("unchecked") private static Object readArray(ByteArrayInputStream stream, String charset, int state) { stream.skip(1); int n = Integer.parseInt(readNumber(stream)); stream.skip(1); Map map = null; List list = null; if (state == 0) { list = new ArrayList(n); state = -1; } else if (state == 1) { map = new TreeMap(); } else { map = new HashMap(n); } for (int i = 0; i < n; i++) { Object key; switch (stream.read()) { case __i: key = readInteger(stream); break; case __s: key = readString(stream, charset); break; case __U: key = readUnicodeString(stream); break; default: return null; } Object result = unserialize(stream, charset, state); if (list != null) { if ((key instanceof Integer) && (((Integer) key).intValue() == i)) { list.add(result); } else { list = null; } } else { map.put(key, result); } } stream.skip(1); if (list != null) { return list; } else { return map; } } }