文件读写方式简单综述后续(文件,流构造)

Java Socket通信实例: http://donald-draper.iteye.com/blog/2356695 
Java Socket读写缓存区Writer和Reader: http://donald-draper.iteye.com/blog/2356885 
Java序列化与反序列化实例分析: http://donald-draper.iteye.com/blog/2357515 
FileChannel示例: http://donald-draper.iteye.com/blog/2373661 
FileChanne定义: http://donald-draper.iteye.com/blog/2374149 
文件读写方式简单综述: http://donald-draper.iteye.com/blog/2374237 
在上一篇文章中看了一下文件读写方式,这天来看一下上次所用到File的方法,和涉及到的概念Path,FileSystem.
先看一下File的内部变量定义; 
Java代码   收藏代码
  1. public class File  
  2.     implements Serializable, Comparable<File>  
  3. {  
  4.   
  5.     /** 
  6.      * The FileSystem object representing the platform's local file system. 
  7.      平台文件系统 
  8.      */  
  9.     static private FileSystem fs = FileSystem.getFileSystem();  
  10.   
  11.     /** 
  12.      * This abstract pathname's normalized pathname string.  A normalized 
  13.      * pathname string uses the default name-separator character and does not 
  14.      * contain any duplicate or redundant separators. 
  15.      *文件标准文件路径字符串。一个标准的路径字符串是用默认的分隔符,不包括 
  16.      冗余的分割符。 
  17.      * @serial 
  18.      */  
  19.     private String path;  
  20.   
  21.     /** 
  22.      * The length of this abstract pathname's prefix, or zero if it has no 
  23.      * prefix.文件前缀长度 
  24.      */  
  25.     private transient int prefixLength;  
  26.     private volatile transient Path filePath;//文件路径Path  
  27.     /** 
  28.      * The system-dependent default name-separator character.  This field is 
  29.      * initialized to contain the first character of the value of the system 
  30.      * property <code>file.separator</code>.  On UNIX systems the value of this 
  31.      * field is <code>'/'</code>; on Microsoft Windows systems it is <code>'\\'</code>. 
  32.      *依赖于平台的默认分隔符。此field初始化为系统属性file.separator。在unix系统中, 
  33.      分割符默认为'/';在Windows中为'\\'。 
  34.      * @see     java.lang.System#getProperty(java.lang.String) 
  35.      */  
  36.     public static final char separatorChar = fs.getSeparator();  
  37.   
  38.     /** 
  39.      * The system-dependent default name-separator character, represented as a 
  40.      * string for convenience.  This string contains a single character, namely 
  41.      * <code>{@link #separatorChar}</code>. 
  42.      依赖于系统的默认分割符,为了便利用String表示。此字符串包含单个字符,为separatorChar。 
  43.      */  
  44.     public static final String separator = "" + separatorChar;  
  45.   
  46.     /** 
  47.      * The system-dependent path-separator character.  This field is 
  48.      * initialized to contain the first character of the value of the system 
  49.      * property <code>path.separator</code>.  This character is used to 
  50.      * separate filenames in a sequence of files given as a [i]path list[/i]. 
  51.      * On UNIX systems, this character is <code>':'</code>; on Microsoft Windows systems it 
  52.      * is <code>';'</code>. 
  53.      *依赖于系统的路径分割符。默认初始化为系统属性path.separator。此字符用于分割 
  54.      在给定path列表中的文件名,在unixt默认为':',windows中为';'。 
  55.      * @see     java.lang.System#getProperty(java.lang.String) 
  56.      */  
  57.     public static final char pathSeparatorChar = fs.getPathSeparator();  
  58.   
  59.     /** 
  60.      * The system-dependent path-separator character, represented as a string 
  61.      * for convenience.  This string contains a single character, namely 
  62.      * <code>{@link #pathSeparatorChar}</code>. 
  63.      依赖系统的路径分割符,为了便利,用于一个String表示。此字符串只包含一个字符,为pathSeparatorChar 
  64.      */  
  65.     public static final String pathSeparator = "" + pathSeparatorChar;  
  66. }  

我们先来看一下这句话,文件系统 
Java代码   收藏代码
  1. static private FileSystem fs = FileSystem.getFileSystem();  

//FileSystem 
Java代码   收藏代码
  1. abstract class FileSystem {  
  2.   
  3.    /** 
  4.     * Return the FileSystem object representing this platform's local 
  5.     * filesystem. 
  6.     */  
  7.    public static native FileSystem getFileSystem();  
  8.    ...  

//Win32FileSystem 
Java代码   收藏代码
  1. class Win32FileSystem extends FileSystem {  
  2.     private final char slash;//文件分割符  
  3.     private final char altSlash;  
  4.     private final char semicolon;//路径分割符  
  5.   
  6.     public Win32FileSystem() {  
  7.         slash = AccessController.doPrivileged(  
  8.             new GetPropertyAction("file.separator")).charAt(0);  
  9.         semicolon = AccessController.doPrivileged(  
  10.             new GetPropertyAction("path.separator")).charAt(0);  
  11.         altSlash = (this.slash == '\\') ? '/' : '\\';  
  12.     }  
  13.     //获取文件分割符  
  14.     public char getSeparator() {  
  15.         return slash;  
  16.     }  
  17.     //获取路径分割符  
  18.     public char getPathSeparator() {  
  19.         return semicolon;  
  20.     }  
  21.     //获取文件系统跟目录  
  22.     public File[] listRoots() {  
  23.         int ds = listRoots0();  
  24.         int n = 0;  
  25.     //获取文件的目录,Windows为C:,D:,  
  26.     //这个循环是获取根目录的盘符,在unix根目录直接为/  
  27.         for (int i = 0; i < 26; i++) {  
  28.             if (((ds >> i) & 1) != 0) {  
  29.                 if (!access((char)('A' + i) + ":" + slash))  
  30.                     ds &= ~(1 << i);  
  31.                 else  
  32.                     n++;  
  33.             }  
  34.         }  
  35.     //更具盘符,文件分隔符,路径分隔符,返回根目录  
  36.         File[] fs = new File[n];  
  37.         int j = 0;  
  38.         char slash = this.slash;  
  39.         for (int i = 0; i < 26; i++) {  
  40.             if (((ds >> i) & 1) != 0)  
  41.                 fs[j++] = new File((char)('A' + i) + ":" + slash);  
  42.         }  
  43.         return fs;  
  44.     }  
  45.     private static native int listRoots0();  
  46.     ...  
  47.     protected native boolean delete0(File f);  
  48.     public native String[] list(File f);  
  49.     public native boolean createDirectory(File f);   
  50.     protected native boolean rename0(File f1, File f2);  
  51.     public native boolean setLastModifiedTime(File f, long time);  
  52.     public native boolean setReadOnly(File f);  
  53.     private native long getSpace0(File f, int t);//获取磁盘空间  
  54.     // Caches for canonicalization results to improve startup performance.  
  55.     // The first cache handles repeated canonicalizations of the same path  
  56.     // name. The prefix cache handles repeated canonicalizations within the  
  57.     // same directory, and must not create results differing from the true  
  58.     // canonicalization algorithm in canonicalize_md.c. For this reason the  
  59.     // prefix cache is conservative and is not used for complex path names.  
  60.     //Caches缓存规范化的结果,以便改善启动性能。cache用于处理相同的规范化路径。  
  61.     //prefixCache用于在相同目录下的前缀,不用创建与canonicalize_md.c算法不同的  
  62.     //结果。prefixCache为保守的用于复杂路径名  
  63.     private ExpiringCache cache       = new ExpiringCache();  
  64.     private ExpiringCache prefixCache = new ExpiringCache();  
  65. }  

我们来看File的listFile方法: 
Java代码   收藏代码
  1. public File[] listFiles() {  
  2.        //获取当前目录下的文件路径  
  3.         String[] ss = list();  
  4.         if (ss == nullreturn null;  
  5.         int n = ss.length;  
  6.         File[] fs = new File[n];  
  7.     //根据路径创建文件  
  8.         for (int i = 0; i < n; i++) {  
  9.             fs[i] = new File(ss[i], this);  
  10.         }  
  11.         return fs;  
  12.     }  

需要关注的是这一点 
//获取当前目录下的文件路径 
Java代码   收藏代码
  1. String[] ss = list();  

//获取文件当前目录下的所有文件路径 
Java代码   收藏代码
  1. public String[] list() {  
  2.        SecurityManager security = System.getSecurityManager();  
  3.        if (security != null) {  
  4.     //检查读取路径权限  
  5.            security.checkRead(path);  
  6.        }  
  7. //委托给文件系统  
  8.        return fs.list(this);  
  9.    }  

//Win32FileSystem 
Java代码   收藏代码
  1. public native String[] list(File f);  



再来看创建临时文件: 
Java代码   收藏代码
  1. File tfile = File.createTempFile("testFile"".tmp"new File("E:/file/dir/"));  
  2.     if(tfile.exists()){  
  3.      System.out.println("==创建临时文件成功:"+tfile.getName());  
  4.     }  

//File 
Java代码   收藏代码
  1. public static File createTempFile(String prefix, String suffix,  
  2.                                       File directory)  
  3.         throws IOException  
  4.     {  
  5.         //如果前缀小于3,则抛出IllegalArgumentException,文件路径最少为3,(D:/),盘符+文件路径分隔符+文件分隔符  
  6.         if (prefix.length() < 3)  
  7.             throw new IllegalArgumentException("Prefix string too short");  
  8.     //文件后缀默认为".tmp";  
  9.         if (suffix == null)  
  10.             suffix = ".tmp";  
  11.         //如果目录为null,获取系统的临时文件路究竟  
  12.         File tmpdir = (directory != null) ? directory : TempDirectory.location();  
  13.         SecurityManager sm = System.getSecurityManager();  
  14.         File f;  
  15.         do {  
  16.         //产生临时文件  
  17.             f = TempDirectory.generateFile(prefix, suffix, tmpdir);  
  18.             if (sm != null) {  
  19.                 try {  
  20.             //检查创建文件路径权限  
  21.                     sm.checkWrite(f.getPath());  
  22.                 } catch (SecurityException se) {  
  23.                     // don't reveal temporary directory location  
  24.                     if (directory == null)  
  25.                         throw new SecurityException("Unable to create temporary file");  
  26.                     throw se;  
  27.                 }  
  28.             }//独占创建文件  
  29.         } while (!fs.createFileExclusively(f.getPath()));  
  30.         return f;  
  31.     }  

来看临时文件的定义 
//TempDirectory 
Java代码   收藏代码
  1. private static class TempDirectory {  
  2.        private TempDirectory() { }  
  3.   
  4.        // temporary directory location  
  5. //文件临时目录为系统的java.io.tmpdir配置  
  6.        private static final File tmpdir = new File(fs.normalize(AccessController  
  7.            .doPrivileged(new GetPropertyAction("java.io.tmpdir"))));  
  8. //返回临时路径  
  9.        static File location() {  
  10.            return tmpdir;  
  11.        }  
  12.   
  13.        // file name generation,临时文件名产生器  
  14.        private static final SecureRandom random = new SecureRandom();  
  15. //生成临时文件  
  16.        static File generateFile(String prefix, String suffix, File dir) {  
  17.     //获取临时文件名  
  18.            long n = random.nextLong();  
  19.            if (n == Long.MIN_VALUE) {  
  20.                n = 0;      // corner case  
  21.            } else {  
  22.                n = Math.abs(n);  
  23.            }  
  24.     //创建文件  
  25.            return new File(dir, prefix + Long.toString(n) + suffix);  
  26.        }  
  27.    }  

再来看删除文件: 
p
Java代码   收藏代码
  1. ublic boolean delete() {  
  2.         SecurityManager security = System.getSecurityManager();  
  3.         if (security != null) {  
  4.             security.checkDelete(path);  
  5.         }  
  6.     //委托给文件系统fs  
  7.         return fs.delete(this);  
  8.     }  

//Win32FileSystem 
Java代码   收藏代码
  1. public boolean delete(File f) {  
  2.         // Keep canonicalization caches in sync after file deletion  
  3.         // and renaming operations. Could be more clever than this  
  4.         // (i.e., only remove/update affected entries) but probably  
  5.         // not worth it since these entries expire after 30 seconds  
  6.         // anyway.  
  7.         cache.clear();  
  8.         prefixCache.clear();  
  9.         return delete0(f);  
  10.     }  
  11.     protected native boolean delete0(File f);  

再来看判断文件是否存在: 
Java代码   收藏代码
  1. public boolean exists() {  
  2.         SecurityManager security = System.getSecurityManager();  
  3.         if (security != null) {  
  4.             security.checkRead(path);  
  5.         }  
  6.         return ((fs.getBooleanAttributes(this) & FileSystem.BA_EXISTS) != 0);  
  7.     }  

//Win32FileSystem 
Java代码   收藏代码
  1. public native int getBooleanAttributes(File f);  

再来看创建路径 
Java代码   收藏代码
  1. public boolean mkdirs() {  
  2.         //存在,返回false  
  3.         if (exists()) {  
  4.             return false;  
  5.         }  
  6.     //mkdir创建成功返回true  
  7.         if (mkdir()) {  
  8.             return true;  
  9.         }  
  10.         File canonFile = null;  
  11.         try {  
  12.             canonFile = getCanonicalFile();  
  13.         } catch (IOException e) {  
  14.             return false;  
  15.         }  
  16.         //获取文件的标准父路径  
  17.         File parent = canonFile.getParentFile();  
  18.         return (parent != null && (parent.mkdirs() || parent.exists()) &&  
  19.                 canonFile.mkdir());  
  20.     }  

//File 
Java代码   收藏代码
  1. public File getCanonicalFile() throws IOException {  
  2.         String canonPath = getCanonicalPath();  
  3.         return new File(canonPath, fs.prefixLength(canonPath));  
  4.     }  
  5. public String getCanonicalPath() throws IOException {  
  6.         return fs.canonicalize(fs.resolve(this));  
  7.     }  

//Win32FileSystem 
Java代码   收藏代码
  1. public String canonicalize(String path) throws IOException {  
  2.         // If path is a drive letter only then skip canonicalization  
  3.         int len = path.length();  
  4.         if ((len == 2) &&  
  5.             (isLetter(path.charAt(0))) &&  
  6.             (path.charAt(1) == ':')) {  
  7.             char c = path.charAt(0);  
  8.             if ((c >= 'A') && (c <= 'Z'))  
  9.                 return path;  
  10.             return "" + ((char) (c-32)) + ':';  
  11.         } else if ((len == 3) &&  
  12.                    (isLetter(path.charAt(0))) &&  
  13.                    (path.charAt(1) == ':') &&  
  14.                    (path.charAt(2) == '\\')) {  
  15.             char c = path.charAt(0);  
  16.             if ((c >= 'A') && (c <= 'Z'))  
  17.                 return path;  
  18.             return "" + ((char) (c-32)) + ':' + '\\';  
  19.         }  
  20.         if (!useCanonCaches) {  
  21.             return canonicalize0(path);  
  22.         } else {  
  23.             String res = cache.get(path);  
  24.             if (res == null) {  
  25.                 String dir = null;  
  26.                 String resDir = null;  
  27.                 if (useCanonPrefixCache) {  
  28.                     dir = parentOrNull(path);  
  29.                     if (dir != null) {  
  30.                         resDir = prefixCache.get(dir);  
  31.                         if (resDir != null) {  
  32.                             // Hit only in prefix cache; full path is canonical,  
  33.                             // but we need to get the canonical name of the file  
  34.                             // in this directory to get the appropriate capitalization  
  35.                             String filename = path.substring(1 + dir.length());  
  36.                             res = canonicalizeWithPrefix(resDir, filename);  
  37.                             cache.put(dir + File.separatorChar + filename, res);  
  38.                         }  
  39.                     }  
  40.                 }  
  41.                 if (res == null) {  
  42.                     res = canonicalize0(path);  
  43.                     cache.put(path, res);  
  44.                     if (useCanonPrefixCache && dir != null) {  
  45.                         resDir = parentOrNull(res);  
  46.                         if (resDir != null) {  
  47.                             File f = new File(res);  
  48.                             if (f.exists() && !f.isDirectory()) {  
  49.                                 prefixCache.put(dir, resDir);  
  50.                             }  
  51.                         }  
  52.                     }  
  53.                 }  
  54.             }  
  55.             return res;  
  56.         }  
  57.     }  
  58. protected native String canonicalize0(String path)  throws IOException;  

上面这个就不说了,这个不是我们关注的重点; 
我们再来看获取文件Path 

Java代码   收藏代码
  1. /* @since   1.7,此方在JDK1.7中才添加 
  2.  * @see Path#toFile 
  3.  */  
  4. public Path toPath() {  
  5.     Path result = filePath;  
  6.     if (result == null) {  
  7.         synchronized (this) {  
  8.             result = filePath;  
  9.             if (result == null) {  
  10.             //从文件系统获取文件路径Path  
  11.                 result = FileSystems.getDefault().getPath(path);  
  12.                 filePath = result;  
  13.             }  
  14.         }  
  15.     }  
  16.     return result;  
  17. }  

来看这一句: 
//从文件系统获取文件路径Path 
Java代码   收藏代码
  1. result = FileSystems.getDefault().getPath(path);  

//FileSystems 
Java代码   收藏代码
  1. public static FileSystem getDefault() {  
  2.     return DefaultFileSystemHolder.defaultFileSystem;  
  3. }  

// lazy initialization of default file system 
 
Java代码   收藏代码
  1. private static class DefaultFileSystemHolder {  
  2.       static final FileSystem defaultFileSystem = defaultFileSystem();  
  3.   
  4.       // returns default file system  
  5.       private static FileSystem defaultFileSystem() {  
  6.           // load default provider  
  7.    //获取文件系统默认的提供者  
  8.           FileSystemProvider provider = AccessController  
  9.               .doPrivileged(new PrivilegedAction<FileSystemProvider>() {  
  10.                   public FileSystemProvider run() {  
  11.                       return getDefaultProvider();  
  12.                   }  
  13.               });  
  14.   
  15.           // return file system  
  16.           return provider.getFileSystem(URI.create("file:///"));  
  17.       }  
  18.   
  19.       // returns default provider,返回默认文件系统提供者  
  20.       private static FileSystemProvider getDefaultProvider() {  
  21.           //默认文件系统提供者,创建FileSystemProvider  
  22.           FileSystemProvider provider = sun.nio.fs.DefaultFileSystemProvider.create();  
  23.   
  24.           // if the property java.nio.file.spi.DefaultFileSystemProvider is  
  25.           // set then its value is the name of the default provider (or a list)  
  26.    //获取系统默认文件提供者配置  
  27.           String propValue = System  
  28.               .getProperty("java.nio.file.spi.DefaultFileSystemProvider");  
  29.           if (propValue != null) {  
  30.               for (String cn: propValue.split(",")) {  
  31.                   try {  
  32.            //系统类加载器,加载文件提供者  
  33.                       Class<?> c = Class  
  34.                           .forName(cn, true, ClassLoader.getSystemClassLoader());  
  35.            //获取文件系统类构造方法  
  36.                       Constructor<?> ctor = c  
  37.                           .getDeclaredConstructor(FileSystemProvider.class);  
  38.            //创建FileSystemProvider  
  39.                       provider = (FileSystemProvider)ctor.newInstance(provider);  
  40.   
  41.                       // must be "file"  
  42.                       if (!provider.getScheme().equals("file"))  
  43.                           throw new Error("Default provider must use scheme 'file'");  
  44.   
  45.                   } catch (Exception x) {  
  46.                       throw new Error(x);  
  47.                   }  
  48.               }  
  49.           }  
  50.           return provider;  
  51.       }  
  52.   }  

我们来看这一句: 
//默认文件系统提供者,创建FileSystemProvider 
Java代码   收藏代码
  1. FileSystemProvider provider = sun.nio.fs.DefaultFileSystemProvider.create();  

//DefaultFileSystemProvider 
Java代码   收藏代码
  1. public class DefaultFileSystemProvider  
  2. {  
  3.     private DefaultFileSystemProvider()  
  4.     {  
  5.     }  
  6.     public static FileSystemProvider create()  
  7.     {  
  8.         return new WindowsFileSystemProvider();  
  9.     }  
  10. }  

默认文件系统提供者为WindowsFileSystemProvider 
返回获取文件路径方法 
Java代码   收藏代码
  1. /* @since   1.7,此方在JDK1.7中才添加 
  2.  * @see Path#toFile 
  3.  */  
  4. public Path toPath() {  
  5.     Path result = filePath;  
  6.     if (result == null) {  
  7.         synchronized (this) {  
  8.             result = filePath;  
  9.             if (result == null) {  
  10.             //从文件系统获取文件路径Path  
  11.                 result = FileSystems.getDefault().getPath(path);  
  12.                 filePath = result;  
  13.             }  
  14.         }  
  15.     }  
  16.     return result;  
  17. }  

//WindowsFileSystemProvider 
Java代码   收藏代码
  1. public class WindowsFileSystemProvider extends AbstractFileSystemProvider  
  2. {  
  3.     private static final Unsafe unsafe = Unsafe.getUnsafe();  
  4.     private static final String USER_DIR = "user.dir";//用户目录  
  5.     private final WindowsFileSystem theFileSystem = new WindowsFileSystem(this, System.getProperty("user.dir"));  
  6.     static final boolean $assertionsDisabled = !sun/nio/fs/WindowsFileSystemProvider.desiredAssertionStatus();  
  7.     public WindowsFileSystemProvider()  
  8.     {  
  9.     }  
  10.     public String getScheme()  
  11.     {  
  12.         return "file";  
  13.     }  
  14.     public Path getPath(URI uri)  
  15.     {  
  16.         return WindowsUriSupport.fromUri(theFileSystem, uri);  
  17.     }  
  18.  }  
  19.  //WindowsUriSupport  
  20.  static WindowsPath fromUri(WindowsFileSystem windowsfilesystem, URI uri)  
  21.     {  
  22.         static WindowsPath fromUri(WindowsFileSystem windowsfilesystem, URI uri)  
  23.     {  
  24.         if(!uri.isAbsolute())  
  25.             throw new IllegalArgumentException("URI is not absolute");  
  26.         if(uri.isOpaque())  
  27.             throw new IllegalArgumentException("URI is not hierarchical");  
  28.         String s = uri.getScheme();  
  29.         if(s == null || !s.equalsIgnoreCase("file"))  
  30.             throw new IllegalArgumentException("URI scheme is not \"file\"");  
  31.         if(uri.getFragment() != null)  
  32.             throw new IllegalArgumentException("URI has a fragment component");  
  33.         if(uri.getQuery() != null)  
  34.             throw new IllegalArgumentException("URI has a query component");  
  35.         String s1 = uri.getPath();  
  36.         if(s1.equals(""))  
  37.             throw new IllegalArgumentException("URI path component is empty");  
  38.         String s2 = uri.getAuthority();  
  39.         if(s2 != null && !s2.equals(""))  
  40.         {  
  41.             String s3 = uri.getHost();  
  42.             if(s3 == null)  
  43.                 throw new IllegalArgumentException("URI authority component has undefined host");  
  44.             if(uri.getUserInfo() != null)  
  45.                 throw new IllegalArgumentException("URI authority component has user-info");  
  46.             if(uri.getPort() != -1)  
  47.                 throw new IllegalArgumentException("URI authority component has port number");  
  48.             if(s3.startsWith("["))  
  49.             {  
  50.                 s3 = s3.substring(1, s3.length() - 1).replace(':''-').replace('%''s');  
  51.                 s3 = (new StringBuilder()).append(s3).append(".ipv6-literal.net").toString();  
  52.             }  
  53.             s1 = (new StringBuilder()).append("\\\\").append(s3).append(s1).toString();  
  54.         } else  
  55.         if(s1.length() > 2 && s1.charAt(2) == ':')  
  56.             s1 = s1.substring(1);  
  57.     //我们需要关注的是这一句  
  58.         return WindowsPath.parse(windowsfilesystem, s1);  
  59.     }  

由于这篇文章是为上一篇文章的后续,这里我们再来看一下字节流和字符流的构造,只是简单列举, 
不打算深入: 
//FileOutputStream 
Java代码   收藏代码
  1. //根据文件名创建FileOutputStream  
  2. public FileOutputStream(String name) throws FileNotFoundException {  
  3.         this(name != null ? new File(name) : nullfalse);  
  4.     }  
  5. //根据文件创建FileOutputStream  
  6.  public FileOutputStream(File file) throws FileNotFoundException {  
  7.         this(file, false);  
  8.     }  
  9.  public FileOutputStream(String name, boolean append)  
  10.         throws FileNotFoundException  
  11.     {  
  12.         this(name != null ? new File(name) : null, append);  
  13.     }  
  14.  //append为是否为追加文件模式  
  15.  public FileOutputStream(File file, boolean append)  
  16.         throws FileNotFoundException  
  17.     {  
  18.         String name = (file != null ? file.getPath() : null);  
  19.         SecurityManager security = System.getSecurityManager();  
  20.         if (security != null) {  
  21.         //检查写文件权限  
  22.             security.checkWrite(name);  
  23.         }  
  24.         if (name == null) {  
  25.             throw new NullPointerException();  
  26.         }  
  27.         this.fd = new FileDescriptor();  
  28.         this.append = append;  
  29.         //系统文件描述符计数器自增  
  30.         fd.incrementAndGetUseCount();  
  31.         open(name, append);  
  32.     }  

//FileInputStream 
Java代码   收藏代码
  1. //根据文件名构造FileInputStream  
  2.  public FileInputStream(String name) throws FileNotFoundException {  
  3.         this(name != null ? new File(name) : null);  
  4.     }  
  5.  public FileInputStream(File file) throws FileNotFoundException {  
  6.         String name = (file != null ? file.getPath() : null);  
  7.         SecurityManager security = System.getSecurityManager();  
  8.         if (security != null) {  
  9.         //检查读权限  
  10.             security.checkRead(name);  
  11.         }  
  12.         if (name == null) {  
  13.             throw new NullPointerException();  
  14.         }  
  15.         fd = new FileDescriptor();  
  16.     //系统文件描述符计数器自增  
  17.         fd.incrementAndGetUseCount();  
  18.         open(name);  
  19.     }  

//BufferedOutputStream 
Java代码   收藏代码
  1. /** 
  2.      * Creates a new buffered output stream to write data to the 
  3.      * specified underlying output stream. 
  4.      * 
  5.      * @param   out   the underlying output stream. 
  6.      */  
  7.     public BufferedOutputStream(OutputStream out) {  
  8.         this(out, 8192);  
  9.     }  
  10.   
  11.     /** 
  12.      * Creates a new buffered output stream to write data to the 
  13.      * specified underlying output stream with the specified buffer 
  14.      * size. 
  15.      * 
  16.      * @param   out    the underlying output stream. 
  17.      * @param   size   the buffer size.//缓冲区size 
  18.      * @exception IllegalArgumentException if size <= 0. 
  19.      */  
  20.     public BufferedOutputStream(OutputStream out, int size) {  
  21.         super(out);  
  22.         if (size <= 0) {  
  23.             throw new IllegalArgumentException("Buffer size <= 0");  
  24.         }  
  25.         buf = new byte[size];  
  26.     }  

//BufferedInputStream 
Java代码   收藏代码
  1. public class BufferedInputStream extends FilterInputStream {  
  2.   
  3.     private static int defaultBufferSize = 8192;  
  4.  /** 
  5.      * Creates a <code>BufferedInputStream</code> 
  6.      * and saves its  argument, the input stream 
  7.      * <code>in</code>, for later use. An internal 
  8.      * buffer array is created and  stored in <code>buf</code>. 
  9.      * 
  10.      * @param   in   the underlying input stream. 
  11.      */  
  12.     public BufferedInputStream(InputStream in) {  
  13.         this(in, defaultBufferSize);  
  14.     }  
  15.   
  16.     /** 
  17.      * Creates a <code>BufferedInputStream</code> 
  18.      * with the specified buffer size, 
  19.      * and saves its  argument, the input stream 
  20.      * <code>in</code>, for later use.  An internal 
  21.      * buffer array of length  <code>size</code> 
  22.      * is created and stored in <code>buf</code>. 
  23.      * 
  24.      * @param   in     the underlying input stream. 
  25.      * @param   size   the buffer size. 
  26.      * @exception IllegalArgumentException if size <= 0. 
  27.      */  
  28.     public BufferedInputStream(InputStream in, int size) {  
  29.         super(in);  
  30.         if (size <= 0) {  
  31.             throw new IllegalArgumentException("Buffer size <= 0");  
  32.         }  
  33.         buf = new byte[size];  
  34.     }  
  35. }  

//DataOutputStream 
Java代码   收藏代码
  1. public DataOutputStream(OutputStream out) {  
  2.        super(out);  
  3.    }  

//DataInputStream 
Java代码   收藏代码
  1. public DataInputStream(InputStream in) {  
  2.         super(in);  
  3.     }  

//ObjectOutputStream 
Java代码   收藏代码
  1. public ObjectOutputStream(OutputStream out) throws IOException {  
  2. ...  
  3. }  

//ObjectInputStream 
Java代码   收藏代码
  1.  public ObjectInputStream(InputStream in) throws IOException {  
  2. ...  
  3. }  

//FileWriter,构造很简单,看一下就明白,不细说了 
Java代码   收藏代码
  1. public class FileWriter extends OutputStreamWriter {  
  2.   
  3.     /** 
  4.      * Constructs a FileWriter object given a file name. 
  5.      * 
  6.      * @param fileName  String The system-dependent filename. 
  7.      * @throws IOException  if the named file exists but is a directory rather 
  8.      *                  than a regular file, does not exist but cannot be 
  9.      *                  created, or cannot be opened for any other reason 
  10.      */  
  11.     public FileWriter(String fileName) throws IOException {  
  12.         super(new FileOutputStream(fileName));  
  13.     }  
  14.   
  15.     /** 
  16.      * Constructs a FileWriter object given a file name with a boolean 
  17.      * indicating whether or not to append the data written. 
  18.      * 
  19.      * @param fileName  String The system-dependent filename. 
  20.      * @param append    boolean if <code>true</code>, then data will be written 
  21.      *                  to the end of the file rather than the beginning. 
  22.      * @throws IOException  if the named file exists but is a directory rather 
  23.      *                  than a regular file, does not exist but cannot be 
  24.      *                  created, or cannot be opened for any other reason 
  25.      */  
  26.     public FileWriter(String fileName, boolean append) throws IOException {  
  27.         super(new FileOutputStream(fileName, append));  
  28.     }  
  29.   
  30.     /** 
  31.      * Constructs a FileWriter object given a File object. 
  32.      * 
  33.      * @param file  a File object to write to. 
  34.      * @throws IOException  if the file exists but is a directory rather than 
  35.      *                  a regular file, does not exist but cannot be created, 
  36.      *                  or cannot be opened for any other reason 
  37.      */  
  38.     public FileWriter(File file) throws IOException {  
  39.         super(new FileOutputStream(file));  
  40.     }  
  41.   
  42.     /** 
  43.      * Constructs a FileWriter object given a File object. If the second 
  44.      * argument is <code>true</code>, then bytes will be written to the end 
  45.      * of the file rather than the beginning. 
  46.      * 
  47.      * @param file  a File object to write to 
  48.      * @param     append    if <code>true</code>, then bytes will be written 
  49.      *                      to the end of the file rather than the beginning 
  50.      * @throws IOException  if the file exists but is a directory rather than 
  51.      *                  a regular file, does not exist but cannot be created, 
  52.      *                  or cannot be opened for any other reason 
  53.      * @since 1.4 
  54.      */  
  55.     public FileWriter(File file, boolean append) throws IOException {  
  56.         super(new FileOutputStream(file, append));  
  57.     }  
  58.   
  59.     /** 
  60.      * Constructs a FileWriter object associated with a file descriptor. 
  61.      * 
  62.      * @param fd  FileDescriptor object to write to. 
  63.      */  
  64.     public FileWriter(FileDescriptor fd) {  
  65.         super(new FileOutputStream(fd));  
  66.     }  
  67. }  

//FileReader 
Java代码   收藏代码
  1. public class FileReader extends InputStreamReader {  
  2.   
  3.    /** 
  4.     * Creates a new <tt>FileReader</tt>, given the name of the 
  5.     * file to read from. 
  6.     * 
  7.     * @param fileName the name of the file to read from 
  8.     * @exception  FileNotFoundException  if the named file does not exist, 
  9.     *                   is a directory rather than a regular file, 
  10.     *                   or for some other reason cannot be opened for 
  11.     *                   reading. 
  12.     */  
  13.     public FileReader(String fileName) throws FileNotFoundException {  
  14.         super(new FileInputStream(fileName));  
  15.     }  
  16.   
  17.    /** 
  18.     * Creates a new <tt>FileReader</tt>, given the <tt>File</tt> 
  19.     * to read from. 
  20.     * 
  21.     * @param file the <tt>File</tt> to read from 
  22.     * @exception  FileNotFoundException  if the file does not exist, 
  23.     *                   is a directory rather than a regular file, 
  24.     *                   or for some other reason cannot be opened for 
  25.     *                   reading. 
  26.     */  
  27.     public FileReader(File file) throws FileNotFoundException {  
  28.         super(new FileInputStream(file));  
  29.     }  
  30.   
  31.    /** 
  32.     * Creates a new <tt>FileReader</tt>, given the 
  33.     * <tt>FileDescriptor</tt> to read from. 
  34.     * 
  35.     * @param fd the FileDescriptor to read from 
  36.     */  
  37.     public FileReader(FileDescriptor fd) {  
  38.         super(new FileInputStream(fd));  
  39.     }  
  40. }  

//BufferedWriter 
Java代码   收藏代码
  1. public class BufferedWriter extends Writer {  
  2.   
  3.     private Writer out;  
  4.   
  5.     private char cb[];  
  6.     private int nChars, nextChar;  
  7.   
  8.     private static int defaultCharBufferSize = 8192;  
  9.     /** 
  10.      * Creates a buffered character-output stream that uses a default-sized 
  11.      * output buffer. 
  12.      * 
  13.      * @param  out  A Writer 
  14.      */  
  15.     public BufferedWriter(Writer out) {  
  16.         this(out, defaultCharBufferSize);  
  17.     }  
  18.   
  19.     /** 
  20.      * Creates a new buffered character-output stream that uses an output 
  21.      * buffer of the given size. 
  22.      * 
  23.      * @param  out  A Writer 
  24.      * @param  sz   Output-buffer size, a positive integer 
  25.      * 
  26.      * @exception  IllegalArgumentException  If sz is <= 0 
  27.      */  
  28.     public BufferedWriter(Writer out, int sz) {  
  29.     ...  
  30.     }  
  31.     ...  
  32. }  

//BufferedReader 
Java代码   收藏代码
  1. public class BufferedReader extends Reader {  
  2.   
  3.     private Reader in;  
  4.   
  5.     private char cb[];  
  6.     private int nChars, nextChar;  
  7.   
  8.     private static final int INVALIDATED = -2;  
  9.     private static final int UNMARKED = -1;  
  10.     private int markedChar = UNMARKED;  
  11.     private int readAheadLimit = 0/* Valid only when markedChar > 0 */  
  12.   
  13.     /** If the next character is a line feed, skip it */  
  14.     private boolean skipLF = false;  
  15.   
  16.     /** The skipLF flag when the mark was set */  
  17.     private boolean markedSkipLF = false;  
  18.   
  19.     private static int defaultCharBufferSize = 8192;  
  20.     private static int defaultExpectedLineLength = 80;  
  21.      /** 
  22.      * Creates a buffering character-input stream that uses a default-sized 
  23.      * input buffer. 
  24.      * 
  25.      * @param  in   A Reader 
  26.      */  
  27.     public BufferedReader(Reader in) {  
  28.         this(in, defaultCharBufferSize);  
  29.     }  
  30.     /** 
  31.      * Creates a buffering character-input stream that uses an input buffer of 
  32.      * the specified size. 
  33.      * 
  34.      * @param  in   A Reader 
  35.      * @param  sz   Input-buffer size 
  36.      * 
  37.      * @exception  IllegalArgumentException  If sz is <= 0 
  38.      */  
  39.     public BufferedReader(Reader in, int sz) {  
  40.         super(in);  
  41.         if (sz <= 0)  
  42.             throw new IllegalArgumentException("Buffer size <= 0");  
  43.         this.in = in;  
  44.         cb = new char[sz];  
  45.         nextChar = nChars = 0;  
  46.     }  
  47.     ...  
  48. }  

字节流和字符流的构造看完,我们来看一下从文件输入输出流,即随机访问文件获取文件通道: 
//FileOutputStream 
Java代码   收藏代码
  1. public FileChannel getChannel() {  
  2.         synchronized (this) {  
  3.             if (channel == null) {  
  4.             //可写不可读  
  5.                 channel = FileChannelImpl.open(fd, falsetrue, append, this);  
  6.   
  7.                 /* 
  8.                  * Increment fd's use count. Invoking the channel's close() 
  9.                  * method will result in decrementing the use count set for 
  10.                  * the channel. 
  11.                  */  
  12.                 fd.incrementAndGetUseCount();  
  13.             }  
  14.             return channel;  
  15.         }  
  16.     }  

//FileInputStream 
Java代码   收藏代码
  1. public FileChannel getChannel() {  
  2.         synchronized (this) {  
  3.             if (channel == null) {  
  4.             //可读不可写  
  5.                 channel = FileChannelImpl.open(fd, truefalsethis);  
  6.   
  7.                 /* 
  8.                  * Increment fd's use count. Invoking the channel's close() 
  9.                  * method will result in decrementing the use count set for 
  10.                  * the channel. 
  11.                  */  
  12.                 fd.incrementAndGetUseCount();  
  13.             }  
  14.             return channel;  
  15.         }  
  16.     }  

//RandomAccessFile 
Java代码   收藏代码
  1. public class RandomAccessFile implements DataOutput, DataInput, Closeable {  
  2.   
  3.     private FileDescriptor fd;  
  4.     private FileChannel channel = null;  
  5.     private boolean rw;//是否读写  
  6.   
  7.     private Object closeLock = new Object();  
  8.     private volatile boolean closed = false;  
  9.   
  10.     private static final int O_RDONLY = 1;  
  11.     private static final int O_RDWR =   2;  
  12.     private static final int O_SYNC =   4;  
  13.     private static final int O_DSYNC =  8;  
  14.  /* @since 1.4 
  15.   * @spec JSR-51 
  16.   */  
  17.  public final FileChannel getChannel() {  
  18.      synchronized (this) {  
  19.          if (channel == null) {  
  20.          //默认可读,在根据rw判断是否可写  
  21.              channel = FileChannelImpl.open(fd, true, rw, this);  
  22.   
  23.              /* 
  24.               * FileDescriptor could be shared by FileInputStream or 
  25.               * FileOutputStream. 
  26.               * Ensure that FD is GC'ed only when all the streams/channels 
  27.               * are done using it. 
  28.               * Increment fd's use count. Invoking the channel's close() 
  29.               * method will result in decrementing the use count set for 
  30.               * the channel. 
  31.               */  
  32.              fd.incrementAndGetUseCount();  
  33.          }  
  34.          return channel;  
  35.      }  
  36.  }  
  37.  ...  
  38.  }  

//FileChannelImpl 
  
Java代码   收藏代码
  1. public static FileChannel open(FileDescriptor filedescriptor, boolean flag, boolean flag1, Object obj)  
  2.    {  
  3.        return new FileChannelImpl(filedescriptor, flag, flag1, false, obj);  
  4.    }  
  5.    public static FileChannel open(FileDescriptor filedescriptor, boolean flag, boolean flag1, boolean flag2, Object obj)  
  6.    {  
  7.        return new FileChannelImpl(filedescriptor, flag, flag1, flag2, obj);  
  8.    }  
  9.    private FileChannelImpl(FileDescriptor filedescriptor, boolean flag, boolean flag1, boolean flag2, Object obj)  
  10.    {  
  11.        fd = filedescriptor;  
  12.        readable = flag;//可读标志  
  13.        writable = flag1;//可写标志  
  14.        append = flag2;//是否尾部追加文件,默认为fasle  
  15. //创建文件通道的对象,为FileInput/OutputStream,  
  16. //RandomAccessFile获取FileSystemProvider(WindowsFileSystemProvider)  
  17.        parent = obj;  
  18.        nd = new FileDispatcherImpl(flag2);  
  19.    }  

FileChannelImpl的读写方法我们在下一篇文件中再说。 

总结: 
file内部关联一个文件系统FileSystem,用于操作底层的系统,file的文件分隔符和路径分隔符都是从FileSystem获取,windows(\\,;)和unix(\,:)有所不同,FileSystem根据底层操作获取不同文件系统实现,windows默认为Win32FileSystem。file的创建,删除,list当前目录文件等待操作,实际是委托给Win32FileSystem。获取文件Path,首先获取文件的默认文件系统提供者,默认WindowsFileSystemProvider,WindowsFileSystemProvider通过文件path(URI),创建文件Path(WindowsPath),这个主要用于创建文件通达需要。 
附: 
//File 

 


 


 

//ExpiringCache 
Java代码   收藏代码
  1. package java.io;  
  2.   
  3. import java.util.Iterator;  
  4. import java.util.Map;  
  5. import java.util.LinkedHashMap;  
  6. import java.util.Set;  
  7.   
  8. class ExpiringCache {  
  9.     private long millisUntilExpiration;  
  10.     private Map  map;  
  11.     // Clear out old entries every few queries  
  12.     private int queryCount;  
  13.     private int queryOverflow = 300;  
  14.     private int MAX_ENTRIES = 200;  
  15.   
  16.     static class Entry {  
  17.         private long   timestamp;  
  18.         private String val;  
  19.   
  20.         Entry(long timestamp, String val) {  
  21.             this.timestamp = timestamp;  
  22.             this.val = val;  
  23.         }  
  24.   
  25.         long   timestamp()                  { return timestamp;           }  
  26.         void   setTimestamp(long timestamp) { this.timestamp = timestamp; }  
  27.   
  28.         String val()                        { return val;                 }  
  29.         void   setVal(String val)           { this.val = val;             }  
  30.     }  
  31.   
  32.     ExpiringCache() {  
  33.         this(30000);  
  34.     }  
  35.   
  36.     ExpiringCache(long millisUntilExpiration) {  
  37.         this.millisUntilExpiration = millisUntilExpiration;  
  38.         map = new LinkedHashMap() {  
  39.             protected boolean removeEldestEntry(Map.Entry eldest) {  
  40.               return size() > MAX_ENTRIES;  
  41.             }  
  42.           };  
  43.     }  
  44.   
  45.     synchronized String get(String key) {  
  46.         if (++queryCount >= queryOverflow) {  
  47.             cleanup();  
  48.         }  
  49.         Entry entry = entryFor(key);  
  50.         if (entry != null) {  
  51.             return entry.val();  
  52.         }  
  53.         return null;  
  54.     }  
  55.   
  56.     synchronized void put(String key, String val) {  
  57.         if (++queryCount >= queryOverflow) {  
  58.             cleanup();  
  59.         }  
  60.         Entry entry = entryFor(key);  
  61.         if (entry != null) {  
  62.             entry.setTimestamp(System.currentTimeMillis());  
  63.             entry.setVal(val);  
  64.         } else {  
  65.             map.put(key, new Entry(System.currentTimeMillis(), val));  
  66.         }  
  67.     }  
  68.   
  69.     synchronized void clear() {  
  70.         map.clear();  
  71.     }  
  72.   
  73.     private Entry entryFor(String key) {  
  74.         Entry entry = (Entry) map.get(key);  
  75.         if (entry != null) {  
  76.             long delta = System.currentTimeMillis() - entry.timestamp();  
  77.             if (delta < 0 || delta >= millisUntilExpiration) {  
  78.                 map.remove(key);  
  79.                 entry = null;  
  80.             }  
  81.         }  
  82.         return entry;  
  83.     }  
  84.   
  85.     private void cleanup() {  
  86.         Set keySet = map.keySet();  
  87.         // Avoid ConcurrentModificationExceptions  
  88.         String[] keys = new String[keySet.size()];  
  89.         int i = 0;  
  90.         for (Iterator iter = keySet.iterator(); iter.hasNext(); ) {  
  91.             String key = (String) iter.next();  
  92.             keys[i++] = key;  
  93.         }  
  94.         for (int j = 0; j < keys.length; j++) {  
  95.             entryFor(keys[j]);  
  96.         }  
  97.         queryCount = 0;  
  98.     }  
  99. }  

//WindowsFileSystemProvider 





//WindowsPath 
Java代码   收藏代码
  1. class WindowsPath extends AbstractPath{  
  2.  private static final int MAX_PATH = 247;  
  3.     private static final int MAX_LONG_PATH = 32000;  
  4.     private final WindowsFileSystem fs;  
  5.     private final WindowsPathType type;  
  6.     private final String root;  
  7.     private final String path;  
  8.     private volatile WeakReference pathForWin32Calls;  
  9.     private volatile Integer offsets[];  
  10.     private int hash;  
  11. }  




 

//URI 
Java代码   收藏代码
  1. public final class URI  
  2.     implements Comparable<URI>, Serializable  
  3. {  
  4.   
  5.     // Note: Comments containing the word "ASSERT" indicate places where a  
  6.     // throw of an InternalError should be replaced by an appropriate assertion  
  7.     // statement once asserts are enabled in the build.  
  8.   
  9.     static final long serialVersionUID = -6052424284110960213L;  
  10.   
  11.   
  12.     // -- Properties and components of this instance --  
  13.   
  14.     // Components of all URIs: [<scheme>:]<scheme-specific-part>[#<fragment>]  
  15.     private transient String scheme;            // null ==> relative URI ,http,file,https,ftp  
  16.     private transient String fragment;  
  17.   
  18.     // Hierarchical URI components: [//<authority>]<path>[?<query>]  
  19.     private transient String authority;         // Registry or server  
  20.   
  21.     // Server-based authority: [<userInfo>@]<host>[:<port>]  
  22.     private transient String userInfo;  
  23.     private transient String host;              // null ==> registry-based  
  24.     private transient int port = -1;            // -1 ==> undefined  
  25.   
  26.     // Remaining components of hierarchical URIs  
  27.     private transient String path;              // null ==> opaque  
  28.     private transient String query;  
  29.   
  30.     // The remaining fields may be computed on demand  
  31.   
  32.     private volatile transient String schemeSpecificPart;  
  33.     private volatile transient int hash;        // Zero ==> undefined  
  34.   
  35.     private volatile transient String decodedUserInfo = null;  
  36.     private volatile transient String decodedAuthority = null;  
  37.     private volatile transient String decodedPath = null;  
  38.     private volatile transient String decodedQuery = null;  
  39.     private volatile transient String decodedFragment = null;  
  40.     private volatile transient String decodedSchemeSpecificPart = null;  
  41. }  

... 
 
... 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值