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字符串中的字符,而且需要在每次反序列化时都需要查找,字符串的查找/匹配占用了没有必要的系统开销。