Java 版本的 PHP serialize/unserialize 完整实现

原创作品,转载请注明出处。

这个版本目前实现了对各种基本类型、数组、ArrayList、HashMap、和其它可序列化对象的序列化。实现了 PHP 5 中的 Serializable 接口的支持。实现了 PHP 中的 __sleep 和 __wakeup 魔术方法的支持。实现了对所有标示(N、b、i、d、s、a、O、R、r、U、C)的反序列化,在对标示 a 反序列化时,可以根据下标和值来自动判断是 ArrayList 还是 HashMap。并且在反序列化时可以强制指定反序列化的类型。

该类是静态类,无需也不能被实例化。除了包含了 serialize 和 unserialize 方法以外,还增加了一个 cast 方法,用来进行反序列化后的类型转换,该方法主要用于将反序列化后的 ArrayList 转化为数组或者 HashMap。

该类在 J2SE SDK 1.3.1 和更高版本上编译通过,更低版本的未做测试。

实现代码

PHPSerializer.java
  1. /* PHPSerializer.java
  2. *
  3. * Author:       Ma Bingyao <andot@ujn.edu.cn>
  4. * Copyright:    CoolCode.CN
  5. * Version:      2.1
  6. * LastModified: 2006-08-09
  7. * This library is free.  You can redistribute it and/or modify it.
  8. * http://www.coolcode.cn/?p=202
  9. */
  10. package org.phprpc.util;
  11.  
  12.  
  13. import java.io.*;
  14. import java.util.*;
  15. import java.lang.reflect.*;
  16.  
  17.  
  18. class UnSerializeResult {
  19.     public Object value;
  20.     public int hv;
  21.     public UnSerializeResult() {}
  22.  
  23.     public UnSerializeResult(Object value, int hv) {
  24.         this.value = value;
  25.         this.hv = hv;
  26.     }
  27. }
  28.  
  29.  
  30. public class PHPSerializer {
  31.     private static Package[] __packages = Package.getPackages();
  32.     private static final byte __Quote = 34;
  33.     private static final byte __0 = 48;
  34.     private static final byte __1 = 49;
  35.     private static final byte __Colon = 58;
  36.     private static final byte __Semicolon = 59;
  37.     private static final byte __C = 67;
  38.     private static final byte __N = 78;
  39.     private static final byte __O = 79;
  40.     private static final byte __R = 82;
  41.     private static final byte __U = 85;
  42.     private static final byte __Slash = 92;
  43.     private static final byte __a = 97;
  44.     private static final byte __b = 98;
  45.     private static final byte __d = 100;
  46.     private static final byte __i = 105;
  47.     private static final byte __r = 114;
  48.     private static final byte __s = 115;
  49.     private static final byte __LeftB = 123;
  50.     private static final byte __RightB = 125;
  51.     private static final String __NAN = new String("NAN");
  52.     private static final String __INF = new String("INF");
  53.     private static final String __NINF = new String("-INF");
  54.     private PHPSerializer() {}
  55.  
  56.     public static byte[] serialize(Object obj) {
  57.         return serialize(obj, "UTF-8");
  58.     }
  59.  
  60.     public static byte[] serialize(Object obj, String charset) {
  61.         HashMap ht = new HashMap();
  62.         int hv = 1;
  63.         ByteArrayOutputStream stream = new ByteArrayOutputStream();
  64.  
  65.         hv = serialize(stream, obj, ht, hv, charset);
  66.         byte[] result = stream.toByteArray();
  67.  
  68.         try {
  69.             stream.close();
  70.         } catch (Exception e) {}
  71.         return result;
  72.     }
  73.  
  74.     public static int serialize(ByteArrayOutputStream stream, Object obj, HashMap ht, int hv, String charset) {
  75.         if (obj == null) {
  76.             hv++;
  77.             writeNull(stream);
  78.         } else {
  79.             if (obj instanceof Boolean) {
  80.                 hv++;
  81.                 writeBoolean(stream, ((Boolean) obj).booleanValue() ? __1 : __0);
  82.             } else if ((obj instanceof Byte) || (obj instanceof Short)
  83.                     || (obj instanceof Integer)) {
  84.                 hv++;
  85.                 writeInteger(stream, getBytes(obj));
  86.             } else if (obj instanceof Long) {
  87.                 hv++;
  88.                 writeDouble(stream, getBytes(obj));
  89.             } else if (obj instanceof Float) {
  90.                 hv++;
  91.                 Float f = (Float) obj;
  92.  
  93.                 if (f.isNaN()) {
  94.                     writeDouble(stream, getBytes(__NAN));
  95.                 } else if (f.isInfinite()) {
  96.                     if (f.floatValue() > 0) {
  97.                         writeDouble(stream, getBytes(__INF));
  98.                     } else {
  99.                         writeDouble(stream, getBytes(__NINF));
  100.                     }
  101.                 } else {
  102.                     writeDouble(stream, getBytes(f));
  103.                 }
  104.             } else if (obj instanceof Double) {
  105.                 hv++;
  106.                 Double d = (Double) obj;
  107.  
  108.                 if (d.isNaN()) {
  109.                     writeDouble(stream, getBytes(__NAN));
  110.                 } else if (d.isInfinite()) {
  111.                     if (d.doubleValue() > 0) {
  112.                         writeDouble(stream, getBytes(__INF));
  113.                     } else {
  114.                         writeDouble(stream, getBytes(__NINF));
  115.                     }
  116.                 } else {
  117.                     writeDouble(stream, getBytes(d));
  118.                 }
  119.             } else if ((obj instanceof Character) || (obj instanceof String)) {
  120.                 hv++;
  121.                 writeString(stream, getBytes(obj, charset));
  122.             } else if (obj.getClass().isArray()) {
  123.                 if (ht.containsKey(new Integer(obj.hashCode()))) {
  124.                     writePointRef(stream, getBytes(ht.get(new Integer(obj.hashCode()))));
  125.                 } else {
  126.                     ht.put(new Integer(obj.hashCode()), new Integer(hv++));
  127.                     hv = writeArray(stream, obj, ht, hv, charset);
  128.                 }
  129.             } else if (obj instanceof ArrayList) {
  130.                 if (ht.containsKey(new Integer(obj.hashCode()))) {
  131.                     writePointRef(stream, getBytes(ht.get(new Integer(obj.hashCode()))));
  132.                 } else {
  133.                     ht.put(new Integer(obj.hashCode()), new Integer(hv++));
  134.                     hv = writeArrayList(stream, (ArrayList) obj, ht, hv, charset);
  135.                 }
  136.             } else if (obj instanceof HashMap) {
  137.                 if (ht.containsKey(new Integer(obj.hashCode()))) {
  138.                     writePointRef(stream, getBytes(ht.get(new Integer(obj.hashCode()))));
  139.                 } else {
  140.                     ht.put(new Integer(obj.hashCode()), new Integer(hv++));
  141.                     hv = writeHashMap(stream, (HashMap) obj, ht, hv, charset);
  142.                 }
  143.             } else {
  144.                 if (ht.containsKey(new Integer(obj.hashCode()))) {
  145.                     hv++;
  146.                     writeRef(stream, getBytes(ht.get(new Integer(obj.hashCode()))));
  147.                 } else {
  148.                     ht.put(new Integer(obj.hashCode()), new Integer(hv++));
  149.                     hv = writeObject(stream, obj, ht, hv, charset);
  150.                 }
  151.             }
  152.         }
  153.         return hv;
  154.     }
  155.  
  156.     private static void writeNull(ByteArrayOutputStream stream) {
  157.         stream.write(__N);
  158.         stream.write(__Semicolon);
  159.     }
  160.  
  161.     private static void writeRef(ByteArrayOutputStream stream, byte[] r) {
  162.         stream.write(__r);
  163.         stream.write(__Colon);
  164.         stream.write(r, 0, r.length);
  165.         stream.write(__Semicolon);
  166.     }
  167.  
  168.     private static void writePointRef(ByteArrayOutputStream stream, byte[] p) {
  169.         stream.write(__R);
  170.         stream.write(__Colon);
  171.         stream.write(p, 0, p.length);
  172.         stream.write(__Semicolon);
  173.     }
  174.  
  175.     private static void writeBoolean(ByteArrayOutputStream stream, byte b) {
  176.         stream.write(__b);
  177.         stream.write(__Colon);
  178.         stream.write(b);
  179.         stream.write(__Semicolon);
  180.     }
  181.  
  182.     private static void writeInteger(ByteArrayOutputStream stream, byte[] i) {
  183.         stream.write(__i);
  184.         stream.write(__Colon);
  185.         stream.write(i, 0, i.length);
  186.         stream.write(__Semicolon);
  187.     }
  188.  
  189.     private static void writeDouble(ByteArrayOutputStream stream, byte[] d) {
  190.         stream.write(__d);
  191.         stream.write(__Colon);
  192.         stream.write(d, 0, d.length);
  193.         stream.write(__Semicolon);
  194.     }
  195.  
  196.     private static void writeString(ByteArrayOutputStream stream, byte[] s) {
  197.         byte[] slen = getBytes(new Integer(s.length));
  198.  
  199.         stream.write(__s);
  200.         stream.write(__Colon);
  201.         stream.write(slen, 0, slen.length);
  202.         stream.write(__Colon);
  203.         stream.write(__Quote);
  204.         stream.write(s, 0, s.length);
  205.         stream.write(__Quote);
  206.         stream.write(__Semicolon);
  207.     }
  208.  
  209.     private static int writeArray(ByteArrayOutputStream stream, Object a, HashMap ht, int hv, String charset) {
  210.         int len = Array.getLength(a);
  211.         byte[] alen = getBytes(new Integer(len));
  212.  
  213.         stream.write(__a);
  214.         stream.write(__Colon);
  215.         stream.write(alen, 0, alen.length);
  216.         stream.write(__Colon);
  217.         stream.write(__LeftB);
  218.         for (int i = 0; i < len; i++) {
  219.             writeInteger(stream, getBytes(new Integer(i)));
  220.             hv = serialize(stream, Array.get(a, i), ht, hv, charset);
  221.         }
  222.         stream.write(__RightB);
  223.         return hv;
  224.     }
  225.  
  226.     private static int writeArrayList(ByteArrayOutputStream stream, ArrayList a, HashMap ht, int hv, String charset) {
  227.         int len = a.size();
  228.         byte[] alen = getBytes(new Integer(len));
  229.  
  230.         stream.write(__a);
  231.         stream.write(__Colon);
  232.         stream.write(alen, 0, alen.length);
  233.         stream.write(__Colon);
  234.         stream.write(__LeftB);
  235.         for (int i = 0; i < len; i++) {
  236.             writeInteger(stream, getBytes(new Integer(i)));
  237.             hv = serialize(stream, a.get(i), ht, hv, charset);
  238.         }
  239.         stream.write(__RightB);
  240.         return hv;
  241.     }
  242.  
  243.     private static int writeHashMap(ByteArrayOutputStream stream, HashMap h, HashMap ht, int hv, String charset) {
  244.         int len = h.size();
  245.         byte[] hlen = getBytes(new Integer(len));
  246.  
  247.         stream.write(__a);
  248.         stream.write(__Colon);
  249.         stream.write(hlen, 0, hlen.length);
  250.         stream.write(__Colon);
  251.         stream.write(__LeftB);
  252.         for (Iterator keys = h.keySet().iterator(); keys.hasNext();) {
  253.             Object key = keys.next();
  254.  
  255.             if ((key instanceof Byte) || (key instanceof Short)
  256.                     || (key instanceof Integer)) {
  257.                 writeInteger(stream, getBytes(key));
  258.             } else if (key instanceof Boolean) {
  259.                 writeInteger(stream, new byte[] { ((Boolean) key).booleanValue() ? __1 : __0 });
  260.             } else {
  261.                 writeString(stream, getBytes(key, charset));
  262.             }
  263.             hv = serialize(stream, h.get(key), ht, hv, charset);
  264.         }
  265.         stream.write(__RightB);
  266.         return hv;
  267.     }
  268.  
  269.     private static int writeObject(ByteArrayOutputStream stream, Object obj, HashMap ht, int hv, String charset) {
  270.         Class cls = obj.getClass();
  271.  
  272.         if (obj instanceof java.io.Serializable) {
  273.             byte[] className = getBytes(getClassName(cls), charset);
  274.             byte[] classNameLen = getBytes(new Integer(className.length));
  275.  
  276.             if (obj instanceof org.phprpc.util.Serializable) {
  277.                 byte[] cs = ((org.phprpc.util.Serializable) obj).serialize();
  278.                 byte[] cslen = getBytes(new Integer(cs.length));
  279.  
  280.                 stream.write(__C);
  281.                 stream.write(__Colon);
  282.                 stream.write(classNameLen, 0, classNameLen.length);
  283.                 stream.write(__Colon);
  284.                 stream.write(__Quote);
  285.                 stream.write(className, 0, className.length);
  286.                 stream.write(__Quote);
  287.                 stream.write(__Colon);
  288.                 stream.write(cslen, 0, cslen.length);
  289.                 stream.write(__Colon);
  290.                 stream.write(__LeftB);
  291.                 stream.write(cs, 0, cs.length);
  292.                 stream.write(__RightB);
  293.             } else {
  294.                 Method __sleep;
  295.  
  296.                 try {
  297.                     __sleep = cls.getMethod("__sleep", new Class[0]);
  298.                 } catch (Exception e) {
  299.                     __sleep = null;
  300.                 }
  301.                 int fl = 0;
  302.                 Field[] f;
  303.  
  304.                 if (__sleep != null) {
  305.                     String[] fieldNames;
  306.  
  307.                     try {
  308.                         __sleep.setAccessible(true);
  309.                         fieldNames = (String[]) __sleep.invoke(obj, new Object[0]);
  310.                     } catch (Exception e) {
  311.                         fieldNames = null;
  312.                     }
  313.                     f = getFields(obj, fieldNames);
  314.                 } else {
  315.                     f = getFields(obj);
  316.                 }
  317.                 AccessibleObject.setAccessible(f, true);
  318.                 byte[] flen = getBytes(new Integer(f.length));
  319.  
  320.                 stream.write(__O);
  321.                 stream.write(__Colon);
  322.                 stream.write(classNameLen, 0, classNameLen.length);
  323.                 stream.write(__Colon);
  324.                 stream.write(__Quote);
  325.                 stream.write(className, 0, className.length);
  326.                 stream.write(__Quote);
  327.                 stream.write(__Colon);
  328.                 stream.write(flen, 0, flen.length);
  329.                 stream.write(__Colon);
  330.                 stream.write(__LeftB);
  331.                 for (int i = 0, len = f.length; i < len; i++) {
  332.                     int mod = f[i].getModifiers();
  333.  
  334.                     if (Modifier.isPublic(mod)) {
  335.                         writeString(stream, getBytes(f[i].getName(), charset));
  336.                     } else if (Modifier.isProtected(mod)) {
  337.                         writeString(stream,
  338.                                 getBytes("\0*\0" + f[i].getName(), charset));
  339.                     } else {
  340.                         writeString(stream,
  341.                                 getBytes(
  342.                                 "\0" + getClassName(f[i].getDeclaringClass())
  343.                                 + "\0" + f[i].getName(),
  344.                                 charset));
  345.                     }
  346.                     Object o;
  347.  
  348.                     try {
  349.                         o = f[i].get(obj);
  350.                     } catch (Exception e) {
  351.                         o = null;
  352.                     }
  353.                     hv = serialize(stream, o, ht, hv, charset);
  354.                 }
  355.                 stream.write(__RightB);
  356.             }
  357.         } else {
  358.             writeNull(stream);
  359.         }
  360.         return hv;
  361.     }
  362.  
  363.     private static byte[] getBytes(Object obj) {
  364.         try {
  365.             return obj.toString().getBytes("US-ASCII");
  366.         } catch (Exception e) {
  367.             return obj.toString().getBytes();
  368.         }
  369.     }
  370.  
  371.     private static byte[] getBytes(Object obj, String charset) {
  372.         try {
  373.             return obj.toString().getBytes(charset);
  374.         } catch (Exception e) {
  375.             return obj.toString().getBytes();
  376.         }
  377.     }
  378.  
  379.     private static String getString(byte[] data, String charset) {
  380.         try {
  381.             return new String(data, charset);
  382.         } catch (Exception e) {
  383.             return new String(data);
  384.         }
  385.     }
  386.  
  387.     private static Class getClass(String className) {
  388.         try {
  389.             Class cls = Class.forName(className);
  390.  
  391.             return cls;
  392.         } catch (Exception e) {}
  393.         for (int i = 0; i < __packages.length; i++) {
  394.             try {
  395.                 Class cls = Class.forName(
  396.                         __packages[i].getName() + "." + className);
  397.  
  398.                 return cls;
  399.             } catch (Exception e) {}
  400.         }
  401.         return null;
  402.     }
  403.  
  404.     private static String getClassName(Class cls) {
  405.         return cls.getName().substring(cls.getPackage().getName().length() + 1);
  406.     }
  407.  
  408.     private static Field getField(Object obj, String fieldName) {
  409.         Class cls = obj.getClass();
  410.  
  411.         while (cls != null) {
  412.             try {
  413.                 Field result = cls.getDeclaredField(fieldName);
  414.                 int mod = result.getModifiers();
  415.  
  416.                 if (Modifier.isFinal(mod) || Modifier.isStatic(mod)) {
  417.                     return null;
  418.                 }
  419.                 return result;
  420.             } catch (Exception e) {}
  421.             cls = cls.getSuperclass();
  422.         }
  423.         return null;
  424.     }
  425.  
  426.     private static Field[] getFields(Object obj, String[] fieldNames) {
  427.         if (fieldNames == null) {
  428.             return getFields(obj);
  429.         }
  430.         int n = fieldNames.length;
  431.         ArrayList fields = new ArrayList(n);
  432.  
  433.         for (int i = 0; i < n; i++) {
  434.             Field f = getField(obj, fieldNames[i]);
  435.  
  436.             if (f != null) {
  437.                 fields.add(f);
  438.             }
  439.         }
  440.         return (Field[]) fields.toArray(new Field[0]);
  441.     }
  442.  
  443.     private static Field[] getFields(Object obj) {
  444.         ArrayList fields = new ArrayList();
  445.         Class cls = obj.getClass();
  446.  
  447.         while (cls != null) {
  448.             Field[] fs = cls.getDeclaredFields();
  449.  
  450.             for (int i = 0; i < fs.length; i++) {
  451.                 int mod = fs[i].getModifiers();
  452.  
  453.                 if (!Modifier.isFinal(mod) && !Modifier.isStatic(mod)) {
  454.                     fields.add(fs[i]);
  455.                 }
  456.             }
  457.             cls = cls.getSuperclass();
  458.         }
  459.         return (Field[]) fields.toArray(new Field[0]);
  460.     }
  461.  
  462.     public static Object newInstance(Class cls) {
  463.         try {
  464.             Constructor ctor = cls.getConstructor(new Class[0]);
  465.             int mod = ctor.getModifiers();
  466.  
  467.             if (Modifier.isPublic(mod)) {
  468.                 return ctor.newInstance(new Object[0]);
  469.             }
  470.         } catch (Exception e) {}
  471.         try {
  472.             Constructor ctor = cls.getConstructor(new Class[] { Integer.TYPE });
  473.             int mod = ctor.getModifiers();
  474.  
  475.             if (Modifier.isPublic(mod)) {
  476.                 return ctor.newInstance(new Object[] { new Integer(0) });
  477.             }
  478.         } catch (Exception e) {}
  479.         try {
  480.             Constructor ctor = cls.getConstructor(new Class[] { Boolean.TYPE });
  481.             int mod = ctor.getModifiers();
  482.  
  483.             if (Modifier.isPublic(mod)) {
  484.                 return ctor.newInstance(new Object[] { new Boolean(false) });
  485.             }
  486.         } catch (Exception e) {}
  487.         try {
  488.             Constructor ctor = cls.getConstructor(new Class[] { String.class });
  489.             int mod = ctor.getModifiers();
  490.  
  491.             if (Modifier.isPublic(mod)) {
  492.                 return ctor.newInstance(new Object[] { "" });
  493.             }
  494.         } catch (Exception e) {}
  495.         Field[] f = cls.getFields();
  496.  
  497.         for (int i = 0; i < f.length; i++) {
  498.             if (f[i].getType() == cls && Modifier.isStatic(f[i].getModifiers())) {
  499.                 try {
  500.                     return f[i].get(null);
  501.                 } catch (Exception e) {}
  502.             }
  503.         }
  504.         Method[] m = cls.getMethods();
  505.  
  506.         for (int i = 0; i < m.length; i++) {
  507.             if (m[i].getReturnType() == cls
  508.                     && Modifier.isStatic(m[i].getModifiers())) {
  509.                 try {
  510.                     return m[i].invoke(null, new Object[0]);
  511.                 } catch (Exception e) {}
  512.                 try {
  513.                     return m[i].invoke(null, new Object[] { new Integer(0) });
  514.                 } catch (Exception e) {}
  515.                 try {
  516.                     return m[i].invoke(null, new Object[] { new Boolean(false) });
  517.                 } catch (Exception e) {}
  518.                 try {
  519.                     return m[i].invoke(null, new Object[] { "" });
  520.                 } catch (Exception e) {}
  521.             }
  522.         }
  523.         return null;
  524.     }
  525.  
  526.     public static Number cast(Number n, Class destClass) {
  527.         if (destClass == Byte.class) {
  528.             return new Byte(n.byteValue());
  529.         }
  530.         if (destClass == Short.class) {
  531.             return new Short(n.shortValue());
  532.         }
  533.         if (destClass == Integer.class) {
  534.             return new Integer(n.intValue());
  535.         }
  536.         if (destClass == Long.class) {
  537.             return new Long(n.longValue());
  538.         }
  539.         if (destClass == Float.class) {
  540.             return new Float(n.floatValue());
  541.         }
  542.         if (destClass == Double.class) {
  543.             return new Double(n.doubleValue());
  544.         }
  545.         return n;
  546.     }
  547.  
  548.     public static Object cast(Object obj, Class destClass) {
  549.         if (obj == null || destClass == null) {
  550.             return obj;
  551.         } else if (obj.getClass() == destClass) {
  552.             return obj;
  553.         } else if (obj instanceof Number) {
  554.             return cast((Number) obj, destClass);
  555.         } else if ((obj instanceof String) && destClass == Character.class) {
  556.             return new Character(((String)obj).charAt(0));
  557.         } else if ((obj instanceof ArrayList) && destClass.isArray()) {
  558.             return toArray((ArrayList) obj, destClass.getComponentType());
  559.         } else if ((obj instanceof ArrayList) && destClass == HashMap.class) {
  560.             return toHashMap((ArrayList) obj);
  561.         } else {
  562.             return obj;
  563.         }
  564.     }
  565.  
  566.     private static HashMap toHashMap(ArrayList a) {
  567.         int n = a.size();
  568.         HashMap h = new HashMap(n);
  569.  
  570.         for (int i = 0; i < n; i++) {
  571.             h.put(new Integer(i), a.get(i));
  572.         }
  573.         return h;
  574.     }
  575.  
  576.     private static Object toArray(ArrayList obj, Class componentType) {
  577.         int n = obj.size();
  578.         Object a = Array.newInstance(componentType, n);
  579.  
  580.         for (int i = 0; i < n; i++) {
  581.             Array.set(a, i, cast(obj.get(i), componentType));
  582.         }
  583.         return a;
  584.     }
  585.  
  586.     private static int getPos(ByteArrayInputStream stream) {
  587.         try {
  588.             Field pos = stream.getClass().getDeclaredField("pos");
  589.  
  590.             pos.setAccessible(true);
  591.             return pos.getInt(stream);
  592.         } catch (Exception e) {
  593.             return 0;
  594.         }
  595.     }
  596.  
  597.     private static void setPos(ByteArrayInputStream stream, int p) {
  598.         try {
  599.             Field pos = stream.getClass().getDeclaredField("pos");
  600.  
  601.             pos.setAccessible(true);
  602.             pos.setInt(stream, p);
  603.         } catch (Exception e) {}
  604.     }
  605.  
  606.     public static Object unserialize(byte[] ss) throws IllegalAccessException {
  607.         return unserialize(ss, null, "UTF-8");
  608.     }
  609.  
  610.     public static Object unserialize(byte[] ss, String charset) throws IllegalAccessException {
  611.         return unserialize(ss, null, charset);
  612.     }
  613.  
  614.     public static Object unserialize(byte[] ss, Class cls) throws IllegalAccessException {
  615.         return unserialize(ss, cls, "UTF-8");
  616.     }
  617.  
  618.     public static Object unserialize(byte[] ss, Class cls, String charset) throws IllegalAccessException {
  619.         int hv = 1;
  620.         ByteArrayInputStream stream = new ByteArrayInputStream(ss);
  621.         Object result = unserialize(stream, new HashMap(), hv, new HashMap(), charset).value;
  622.  
  623.         try {
  624.             stream.close();
  625.         } catch (Exception e) {}
  626.         return cast(result, cls);
  627.     }
  628.  
  629.     private static UnSerializeResult unserialize(ByteArrayInputStream stream, HashMap ht, int hv, HashMap rt, String charset) throws IllegalAccessException {
  630.         Object obj;
  631.  
  632.         switch (stream.read()) {
  633.         case __N:
  634.             obj = readNull(stream);
  635.             ht.put(new Integer(hv++), obj);
  636.             return new UnSerializeResult(obj, hv);
  637.  
  638.         case __b:
  639.             obj = readBoolean(stream);
  640.             ht.put(new Integer(hv++), obj);
  641.             return new UnSerializeResult(obj, hv);
  642.  
  643.         case __i:
  644.             obj = readInteger(stream);
  645.             ht.put(new Integer(hv++), obj);
  646.             return new UnSerializeResult(obj, hv);
  647.  
  648.         case __d:
  649.             obj = readDouble(stream);
  650.             ht.put(new Integer(hv++), obj);
  651.             return new UnSerializeResult(obj, hv);
  652.  
  653.         case __s:
  654.             obj = readString(stream, charset);
  655.             ht.put(new Integer(hv++), obj);
  656.             return new UnSerializeResult(obj, hv);
  657.  
  658.         case __U:
  659.             obj = readUnicodeString(stream);
  660.             ht.put(new Integer(hv++), obj);
  661.             return new UnSerializeResult(obj, hv);
  662.  
  663.         case __r:
  664.             return readRef(stream, ht, hv, rt);
  665.  
  666.         case __a:
  667.             return readArray(stream, ht, hv, rt, charset);
  668.  
  669.         case __O:
  670.             return readObject(stream, ht, hv, rt, charset);
  671.  
  672.         case __C:
  673.             return readCustomObject(stream, ht, hv, charset);
  674.  
  675.         case __R:
  676.             return readPointRef(stream, ht, hv, rt);
  677.  
  678.         default:
  679.             return null;
  680.         }
  681.     }
  682.  
  683.     private static String readNumber(ByteArrayInputStream stream) {
  684.         StringBuffer sb = new StringBuffer();
  685.         int i = stream.read();
  686.  
  687.         while ((i != __Semicolon) && (i != __Colon)) {
  688.             sb.append((char) i);
  689.             i = stream.read();
  690.         }
  691.         return sb.toString();
  692.     }
  693.  
  694.     private static Object readNull(ByteArrayInputStream stream) {
  695.         stream.skip(1);
  696.         return null;
  697.     }
  698.  
  699.     private static Boolean readBoolean(ByteArrayInputStream stream) {
  700.         stream.skip(1);
  701.         Boolean b = new Boolean(stream.read() == __1);
  702.  
  703.         stream.skip(1);
  704.         return b;
  705.     }
  706.  
  707.     private static Number readInteger(ByteArrayInputStream stream) {
  708.         stream.skip(1);
  709.         String i = readNumber(stream);
  710.  
  711.         try {
  712.             return new Byte(i);
  713.         } catch (Exception e1) {
  714.             try {
  715.                 return new Short(i);
  716.             } catch (Exception e2) {
  717.                 return new Integer(i);
  718.             }
  719.         }
  720.     }
  721.  
  722.     private static Number readDouble(ByteArrayInputStream stream) {
  723.         stream.skip(1);
  724.         String d = readNumber(stream);
  725.  
  726.         if (d.equals(__NAN)) {
  727.             return new Double(Double.NaN);
  728.         }
  729.         if (d.equals(__INF)) {
  730.             return new Double(Double.POSITIVE_INFINITY);
  731.         }
  732.         if (d.equals(__NINF)) {
  733.             return new Double(Double.NEGATIVE_INFINITY);
  734.         }
  735.         try {
  736.             return new Long(d);
  737.         } catch (Exception e1) {
  738.             try {
  739.                 Float f = new Float(d);
  740.  
  741.                 if (f.isInfinite()) {
  742.                     return new Double(d);
  743.                 } else {
  744.                     return f;
  745.                 }
  746.             } catch (Exception e2) {
  747.                 return new Float(0);
  748.             }
  749.         }
  750.     }
  751.  
  752.     private static String readString(ByteArrayInputStream stream, String charset) {
  753.         stream.skip(1);
  754.         int len = Integer.parseInt(readNumber(stream));
  755.  
  756.         stream.skip(1);
  757.         byte[] buf = new byte[len];
  758.  
  759.         stream.read(buf, 0, len);
  760.         String s = getString(buf, charset);
  761.  
  762.         stream.skip(2);
  763.         return s;
  764.     }
  765.  
  766.     private static String readUnicodeString(ByteArrayInputStream stream) {
  767.         stream.skip(1);
  768.         int l = Integer.parseInt(readNumber(stream));
  769.  
  770.         stream.skip(1);
  771.         StringBuffer sb = new StringBuffer(l);
  772.         int c;
  773.  
  774.         for (int i = 0; i < l; i++) {
  775.             if ((c = stream.read()) == __Slash) {
  776.                 char c1 = (char) stream.read();
  777.                 char c2 = (char) stream.read();
  778.                 char c3 = (char) stream.read();
  779.                 char c4 = (char) stream.read();
  780.  
  781.                 sb.append(
  782.                         (char) (Integer.parseInt(
  783.                                 new String(new char[] { c1, c2, c3, c4 }), 16)));
  784.             } else {
  785.                 sb.append((char) c);
  786.             }
  787.         }
  788.         stream.skip(2);
  789.         return sb.toString();
  790.     }
  791.  
  792.     private static UnSerializeResult readRef(ByteArrayInputStream stream, HashMap ht, int hv, HashMap rt) {
  793.         stream.skip(1);
  794.         Integer r = new Integer(readNumber(stream));
  795.  
  796.         if (rt.containsKey(r)) {
  797.             rt.put(r, new Boolean(true));
  798.         }
  799.         Object obj = ht.get(r);
  800.  
  801.         ht.put(new Integer(hv++), obj);
  802.         return new UnSerializeResult(obj, hv);
  803.     }
  804.  
  805.     private static UnSerializeResult readPointRef(ByteArrayInputStream stream, HashMap ht, int hv, HashMap rt) {
  806.         stream.skip(1);
  807.         Integer r = new Integer(readNumber(stream));
  808.  
  809.         if (rt.containsKey(r)) {
  810.             rt.put(r, new Boolean(true));
  811.         }
  812.         Object obj = ht.get(r);
  813.  
  814.         return new UnSerializeResult(obj, hv);
  815.     }
  816.  
  817.     private static UnSerializeResult readArray(ByteArrayInputStream stream, HashMap ht, int hv, HashMap rt, String charset) throws IllegalAccessException {
  818.         stream.skip(1);
  819.         int n = Integer.parseInt(readNumber(stream));
  820.  
  821.         stream.skip(1);
  822.         HashMap h = new HashMap(n);
  823.         ArrayList al = new ArrayList(n);
  824.         Integer r = new Integer(hv);
  825.  
  826.         rt.put(r, new Boolean(false));
  827.         int p = getPos(stream);
  828.  
  829.         ht.put(new Integer(hv++), h);
  830.         for (int i = 0; i < n; i++) {
  831.             Object key;
  832.  
  833.             switch (stream.read()) {
  834.             case __i:
  835.                 key = cast(readInteger(stream), Integer.class);
  836.                 break;
  837.  
  838.             case __s:
  839.                 key = readString(stream, charset);
  840.                 break;
  841.  
  842.             case __U:
  843.                 key = readUnicodeString(stream);
  844.                 break;
  845.  
  846.             default:
  847.                 return null;
  848.             }
  849.             UnSerializeResult result = unserialize(stream, ht, hv, rt, charset);
  850.  
  851.             hv = result.hv;
  852.             if (al != null) {
  853.                 if ((key instanceof Integer) && (((Integer) key).intValue() == i)) {
  854.                     al.add(result.value);
  855.                 } else {
  856.                     al = null;
  857.                 }
  858.             }
  859.             h.put(key, result.value);
  860.         }
  861.         if (al != null) {
  862.             ht.put(r, al);
  863.             if (((Boolean) (rt.get(r))).booleanValue()) {
  864.                 hv = r.intValue() + 1;
  865.                 setPos(stream, p);
  866.                 for (int i = 0; i < n; i++) {
  867.                     int key;
  868.  
  869.                     switch (stream.read()) {
  870.                     case __i:
  871.                         key = ((Integer) cast(readInteger(stream), Integer.class)).intValue();
  872.                         break;
  873.  
  874.                     default:
  875.                         return null;
  876.                     }
  877.                     UnSerializeResult result = unserialize(stream, ht, hv, rt,
  878.                             charset);
  879.  
  880.                     hv = result.hv;
  881.                     al.set(key, result.value);
  882.                 }
  883.             }
  884.         }
  885.         rt.remove(r);
  886.         stream.skip(1);
  887.         return new UnSerializeResult(ht.get(r), hv);
  888.     }
  889.  
  890.     private static UnSerializeResult readObject(ByteArrayInputStream stream, HashMap ht, int hv, HashMap rt, String charset) throws IllegalAccessException {
  891.         stream.skip(1);
  892.         int len = Integer.parseInt(readNumber(stream));
  893.  
  894.         stream.skip(1);
  895.         byte[] buf = new byte[len];
  896.  
  897.         stream.read(buf, 0, len);
  898.         String cn = getString(buf, charset);
  899.  
  900.         stream.skip(2);
  901.         int n = Integer.parseInt(readNumber(stream));
  902.  
  903.         stream.skip(1);
  904.         Class cls = getClass(cn);
  905.         Object o;
  906.  
  907.         if (cls != null) {
  908.             if ((o = newInstance(cls)) == null) {
  909.                 o = new HashMap(n);
  910.             }
  911.         } else {
  912.             o = new HashMap(n);
  913.         }
  914.         ht.put(new Integer(hv++), o);
  915.         for (int i = 0; i < n; i++) {
  916.             String key;
  917.  
  918.             switch (stream.read()) {
  919.             case __s:
  920.                 key = readString(stream, charset);
  921.                 break;
  922.  
  923.             case __U:
  924.                 key = readUnicodeString(stream);
  925.                 break;
  926.  
  927.             default:
  928.                 return null;
  929.             }
  930.             if (key.charAt(0) == (char) 0) {
  931.                 key = key.substring(key.indexOf("\0", 1) + 1);
  932.             }
  933.             UnSerializeResult result = unserialize(stream, ht, hv, rt, charset);
  934.  
  935.             hv = result.hv;
  936.             if (o instanceof HashMap) {
  937.                 ((HashMap) o).put(key, result.value);
  938.             } else {
  939.                 Field f = getField(o, key);
  940.  
  941.                 f.setAccessible(true);
  942.                 f.set(o, result.value);
  943.             }
  944.         }
  945.         stream.skip(1);
  946.         Method __wakeup = null;
  947.  
  948.         try {
  949.             __wakeup = o.getClass().getMethod("__wakeup", new Class[0]);
  950.             __wakeup.invoke(o, new Object[0]);
  951.         } catch (Exception e) {}
  952.         return new UnSerializeResult(o, hv);
  953.     }
  954.  
  955.     private static UnSerializeResult readCustomObject(ByteArrayInputStream stream, HashMap ht, int hv, String charset) {
  956.         stream.skip(1);
  957.         int len = Integer.parseInt(readNumber(stream));
  958.  
  959.         stream.skip(1);
  960.         byte[] buf = new byte[len];
  961.  
  962.         stream.read(buf, 0, len);
  963.         String cn = getString(buf, charset);
  964.  
  965.         stream.skip(2);
  966.         int n = Integer.parseInt(readNumber(stream));
  967.  
  968.         stream.skip(1);
  969.         Class cls = getClass(cn);
  970.         Object o;
  971.  
  972.         if (cls != null) {
  973.             o = newInstance(cls);
  974.         } else {
  975.             o = null;
  976.         }
  977.         ht.put(new Integer(hv++), o);
  978.         if (o == null) {
  979.             stream.skip(n);
  980.         } else if (o instanceof org.phprpc.util.Serializable) {
  981.             byte[] b = new byte[n];
  982.  
  983.             stream.read(b, 0, n);
  984.             ((org.phprpc.util.Serializable) o).unserialize(b);
  985.         } else {
  986.             stream.skip(n);
  987.         }
  988.         stream.skip(1);
  989.         return new UnSerializeResult(o, hv);
  990.     }
  991. }
  1. /* Serializable.java
  2. *
  3. * Author:       Ma Bingyao <andot@ujn.edu.cn>
  4. * Copyright:    CoolCode.CN
  5. * Version:      2.1
  6. * LastModified: 2006-08-09
  7. * This library is free.  You can redistribute it and/or modify it.
  8. * http://www.coolcode.cn/?p=202
  9. */
  10. package org.phprpc.util;
  11.  
  12.  
  13. interface Serializable {
  14.     byte[] serialize();
  15.     void unserialize(byte[] ss);
  16. }

标签: PHP, Java

« 上一篇 | 下一篇 »

只显示10条记录相关文章

2 条回复至 "Java 版本的 PHP serialize/unserialize 完整实现" 的评论

写的很好,我转啦

choujone.com 于 2012-12-27 15:04:00 提交#1

辛苦了 多谢

由 yyy 于 2011-07-06 15:17:37 提交#2


发表评论

评论 (必须):