JDK源代码粗读——File类的序列化与反序列化

  java.io.File类可用于操作文件系统中的文件与目录,包括获取文件/目录的基本信息,创建,删除目录/文件。除了读、写文件,其它所有操作File类都可以完成。

  File类实现了Serializable接口,可序列化。同时,File类通过writeObject(ObjectOutputStream oos)与 readObject(ObjectInputStream ois)两个方法实现了定制的序列化操作。将File实例序列化以及反序列化,是为了跨应用或者跨平台地定位、获取一个文件/目录。而Windows平台与UNIX平台的地址分隔符是不同的,在UNIX平台下,地址分隔符为“/”,在Windows平台下,地址分隔符为“\”,在Java中还需要添加转义,最后形式为“\\”:

UNIX:    "/home/zhenxuan/test.txt"

Windows    "C:\\Users\\test.txt"

  File实例中,有实例变量存储文件/目录路径的path 字符串变量中存储。path变量是经过标准化的,文件路径中的分隔符为当前平台的默认分隔符。平台默认的分隔符为类变量separatorChar中,定义该变量的代码为:

 public static final char separatorChar = fs.getSeparator();

 类变量无法序列化到二进制流中,当然也无法从二进制流中通过反序列化得到。因此File类在自定义序列化操作时,针对地址中分隔符的区别,向二进制流中写入了一个代表地址分隔符的字符,在自定义的反序列化操作中,通过比较代表地址分隔符的字符与本平台的分隔符的异同,决定替换path中的分隔符或者不进行替换。

File类自定义的序列化操作,将separatorChar写入了二进制流:

1  private synchronized void writeObject(java.io.ObjectOutputStream s)
2         throws IOException
3     {
4         s.defaultWriteObject();
5         s.writeChar(separatorChar); // Add the separator character
6     }

File类自定义的反序列化操作:

 1 private synchronized void readObject(java.io.ObjectInputStream s)
 2          throws IOException, ClassNotFoundException
 3     {
 4         ObjectInputStream.GetField fields = s.readFields();
 5         String pathField = (String)fields.get("path", null);
 6         char sep = s.readChar(); // read the previous separator char
 7         if (sep != separatorChar)
 8             pathField = pathField.replace(sep, separatorChar);
 9         String path = fs.normalize(pathField);
10         UNSAFE.putObject(this, PATH_OFFSET, path);
11         UNSAFE.putIntVolatile(this, PREFIX_LENGTH_OFFSET, fs.prefixLength(path));
12     }

通过自定义的序列化操作,可以方便地确定path变量是否需要更改。而其它判断path变量是否需要更改的方法,必须涉及到查找path字符串中的字符,而且需要在每次反序列化时都需要查找,字符串的查找/匹配占用了没有必要的系统开销。

posted @ 2015-08-10 14:07  王振璇  阅读(420)  评论(0编辑  收藏  举报