java.nio.file.Path(Jdk7)与java.io.File比较

Path 类是jdk7新增加的特性之一,用来代替java.io.File类。

之所以新增这个类,是由于java.io.File类有很多缺陷:

1.java.io.File类里面很多方法失败时没有异常处理,或抛出异常,例如:

public boolean delete() {  
       SecurityManager security = System.getSecurityManager();  
       if (security != null) {  
           security.checkDelete(path);  
       }  
       return fs.delete(this);  
   }

 java.io.File.delete()方法返回一个布尔值指示成功或失败但是没有失败原因。而java.nio.file.Files.delete(Path):

public static void delete(Path path) throws IOException {  
        provider(path).delete(path);  
    }

这个方法会抛出:NoSuchFileException,DirectoryNotEmptyException,IOException,SecurityException这样当删除一个文件失败时可以根据异常来查找失败原因。

例如:

package io.path;  
  
import java.io.IOException;  
import java.nio.file.Files;  
import java.nio.file.Path;  
import java.nio.file.Paths;  
  
public class DeleteFile {  
  
    public static void main(String[] args) throws IOException {  
        Path path = Paths.get("H://afile");//This path does not exsit in file system.  
        Files.delete(path);  
    }  
}

运行结果:

Exception in thread "main" java.nio.file.NoSuchFileException: H:\afile
at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:79)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
at sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:268)
at sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:103)
at java.nio.file.Files.delete(Files.java:1077)
at io.path.DeleteFile.main(DeleteFile.java:12)

2.java.io.File.rename(File file)方法在不同平台中运行时可能会有问题,这个方法不能将一个文件从一个文件系统移到另一个文件系统,这个方法的操作也不是原子性的,如果参数指定的文件名已经存在这个方法也可能执行失败:

package io.path;  
  
import java.io.File;  
import java.io.IOException;  
import java.nio.file.CopyOption;  
import java.nio.file.Files;  
import java.nio.file.Path;  
import java.nio.file.Paths;  
import java.nio.file.StandardCopyOption;  
  
public class FileRename {  
  
    /** 
     * Expected Result: rename beforeRename1.txt to rename1.txt; beforeRename1.txt disappears; and the content of 
     * rename1.txt is the same with beforeRename1.txt 
     */  
    public static void rename1() {  
  
        File file = new File("D:\\360云盘\\javase\\src\\io\\beforeRename1.txt");// The content of beforeRename1.txt is a  
                                                                              // string  
                                                                              // with value "1111"  
  
        File destinationfile1 = new File("D:\\360云盘\\javase\\src\\io\\rename1.txt");// rename1.txt has already  
                                                                                    // existed. and the content is null.  
        file.renameTo(destinationfile1);  
    }  
  
    /** 
     * Expected Result: rename beforeRename2.txt to rename2.txt ;beforeRename2.txt disappears; and the content of 
     * rename2.txt is the same with beforeRename2.txt,that is "2222" 
     */  
    public static void rename2() {  
  
        File file = new File("D:\\360云盘\\javase\\src\\io\\beforeRename2.txt");// The content of beforeRename2.txt is a  
                                                                              // string  
                                                                              // with value "2222"  
  
        File destinationfile2 = new File("D:\\360云盘\\javase\\src\\io\\rename2.txt");// rename2.txt does not exist.  
        file.renameTo(destinationfile2);  
    }  
  
      
    /** 
     * Expected Result: rename beforeRename3.txt to rename3.txt ;beforeRename3.txt disappears; and the content of 
     * rename3.txt is the same with beforeRename3.txt ,that is "3333" 
     */  
    public static void rename3() throws IOException {  
        Path path = Paths.get("D:\\360云盘\\javase\\src\\io\\beforeRename3.txt");// The content of beforeRename3.txt is a  
                                                                               // string with value of "3333"  
  
        Path pathRename = Paths.get("D:\\360云盘\\javase\\src\\io\\rename3.txt");// rename3.txt has already existed,and  
                                                                               // the content is null.  
  
        Files.move(path, pathRename, StandardCopyOption.REPLACE_EXISTING);  
    }  
  
    public static void main(String[] args) throws IOException {  
//        rename1();  
//        rename2();  
        rename3();  
    }  
}

上面这个类中,执行之后会发现,beforeRename1.txt依然还在,rename1.txt的文件内容也米有改变,而beforeRename2.txt文件已经被重命名为rename2.txt,而且rename2.txt的内容与beforeRename2.txt的内容一样 为“2222”。但是如果使用java.nio.Files.move(Path source, Path target, CopyOption… options)可以发现即使 rename3已经存在,也可以把beforeRename3.txt成功的重命名为rename3.txt

3. 读取文件属性相关

File类中读取文件属性都是一个方法返回一个属性值,而没有能够直接一次返回很多属性的方法,造成访问文件属性时效率的问题。

但是对于jkd7新增的api中可以批量读取文件属性,而且可以访问到文件更详细的属性。

package io.path;  
  
import java.io.File;  
import java.io.IOException;  
import java.nio.file.Files;  
import java.nio.file.LinkOption;  
import java.nio.file.Path;  
import java.nio.file.Paths;  
import java.nio.file.attribute.BasicFileAttributes;  
import java.util.Map;  
  
public class FileAttribute {  
  
    public static void main(String[] args) throws IOException {  
        // ==============Get attribute by File=========================  
        File file = new File("D:\\360云盘\\javase\\src\\io\\path.txt");  
        System.out.println("isDirectory:" + file.isDirectory());  
        System.out.println("isHidden:" + file.isHidden());  
        System.out.println("canRead:" + file.canRead());  
        System.out.println("canWrite:" + file.canWrite());  
        System.out.println("lastModified:" + file.lastModified());  
        System.out.println("length:" + file.length());  
  
        // ==============Get attribute by Path=========================  
  
        Path path = Paths.get("D:\\360云盘\\javase\\src\\io\\path.txt");  
        readAttributes(path, "*", LinkOption.NOFOLLOW_LINKS);  
        System.out.println(Files.getOwner(path, LinkOption.NOFOLLOW_LINKS).getName());  
  
        BasicFileAttributes attributes = Files.readAttributes(path, BasicFileAttributes.class,  
                LinkOption.NOFOLLOW_LINKS);  
        System.out.println(attributes.fileKey());  
        System.out.println(attributes.isOther());  
    }  
  
    /** 
     *  
     * @param path 
     * @param attributes 
     * @param linkOption 
     * @throws IOException 
     */  
    public static void readAttributes(Path path, String attributes, LinkOption... linkOption) throws IOException {  
        Map<String, Object> map = Files.readAttributes(path, attributes, linkOption);  
        for (String s : map.keySet()) {  
            System.out.println(s + ":" + map.get(s));  
        }  
    }  
  
}

除了以上还有其它一些问题,例如file.list();方法在处理比较大的目录时效率很低,但是为什么效率低?而java.nio.file是怎样优化的呢?没搞清楚………

转自:http://grapes-peng.iteye.com/blog/1882917