• Java文件IO操作应该抛弃File拥抱Paths和Files


    Java7中文件IO发生了很大的变化,专门引入了很多新的类:

    import java.nio.file.DirectoryStream;
    import java.nio.file.FileSystem;
    import java.nio.file.FileSystems;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.nio.file.attribute.FileAttribute;
    import java.nio.file.attribute.PosixFilePermission;
    import java.nio.file.attribute.PosixFilePermissions;

    ......等等,来取代原来的基于java.io.File的文件IO操作方式.

    1. Path就是取代File的

    Path represents a path that is hierarchical and composed of a sequence of directory and file name elements separated by a special separator or delimiter.

    Path用于来表示文件路径和文件。可以有多种方法来构造一个Path对象来表示一个文件路径,或者一个文件:

    1)首先是final类Paths的两个static方法,如何从一个路径字符串来构造Path对象:

            Path path = Paths.get("C:/", "Xmp");
            Path path2 = Paths.get("C:/Xmp");
            
            URI u = URI.create("file:///C:/Xmp/dd");        
            Path p = Paths.get(u);

    2)FileSystems构造:

    Path path3 = FileSystems.getDefault().getPath("C:/", "access.log");

    3)File和Path之间的转换,File和URI之间的转换:

            File file = new File("C:/my.ini");
            Path p1 = file.toPath();
            p1.toFile();
            file.toURI();

    4)创建一个文件:

    复制代码
            Path target2 = Paths.get("C:\mystuff.txt");
    //      Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rw-rw-rw-");
    //      FileAttribute<Set<PosixFilePermission>> attrs = PosixFilePermissions.asFileAttribute(perms);
            try {
                if(!Files.exists(target2))
                    Files.createFile(target2);
            } catch (IOException e) {
                e.printStackTrace();
            }
    复制代码

    windows下不支持PosixFilePermission来指定rwx权限。

    5)Files.newBufferedReader读取文件:

    复制代码
            try {
    //            Charset.forName("GBK")
                BufferedReader reader = Files.newBufferedReader(Paths.get("C:\my.ini"), StandardCharsets.UTF_8);
                String str = null;
                while((str = reader.readLine()) != null){
                    System.out.println(str);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
    复制代码

    可以看到使用 Files.newBufferedReader 远比原来的FileInputStream,然后BufferedReader包装,等操作简单的多了。

    这里如果指定的字符编码不对,可能会抛出异常 MalformedInputException ,或者读取到了乱码:

    复制代码
    java.nio.charset.MalformedInputException: Input length = 1
        at java.nio.charset.CoderResult.throwException(CoderResult.java:281)
        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:339)
        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
        at java.io.InputStreamReader.read(InputStreamReader.java:184)
        at java.io.BufferedReader.fill(BufferedReader.java:161)
        at java.io.BufferedReader.readLine(BufferedReader.java:324)
        at java.io.BufferedReader.readLine(BufferedReader.java:389)
        at com.coin.Test.main(Test.java:79)
    复制代码

    6)文件写操作:

    复制代码
            try {
                BufferedWriter writer = Files.newBufferedWriter(Paths.get("C:\my2.ini"), StandardCharsets.UTF_8);
                writer.write("测试文件写操作");
                writer.flush();
                writer.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
    复制代码

    7)遍历一个文件夹:

    复制代码
            Path dir = Paths.get("D:\webworkspace");
            try(DirectoryStream<Path> stream = Files.newDirectoryStream(dir)){
                for(Path e : stream){
                    System.out.println(e.getFileName());
                }
            }catch(IOException e){
                
            }
    复制代码
    复制代码
            try (Stream<Path> stream = Files.list(Paths.get("C:/"))){
                Iterator<Path> ite = stream.iterator();
                while(ite.hasNext()){
                    Path pp = ite.next();
                    System.out.println(pp.getFileName());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
    复制代码

    上面是遍历单个目录,它不会遍历整个目录。遍历整个目录需要使用:Files.walkFileTree

    8)遍历整个文件目录:

    复制代码
        public static void main(String[] args) throws IOException{
            Path startingDir = Paths.get("C:\apache-tomcat-8.0.21");
            List<Path> result = new LinkedList<Path>();
            Files.walkFileTree(startingDir, new FindJavaVisitor(result));
            System.out.println("result.size()=" + result.size());        
        }
        
        private static class FindJavaVisitor extends SimpleFileVisitor<Path>{
            private List<Path> result;
            public FindJavaVisitor(List<Path> result){
                this.result = result;
            }
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs){
                if(file.toString().endsWith(".java")){
                    result.add(file.getFileName());
                }
                return FileVisitResult.CONTINUE;
            }
        }
    复制代码

    来一个实际例子:

    复制代码
        public static void main(String[] args) throws IOException {
            Path startingDir = Paths.get("F:\upload\images");    // F:\upload\images\2\20141206
            List<Path> result = new LinkedList<Path>();
            Files.walkFileTree(startingDir, new FindJavaVisitor(result));
            System.out.println("result.size()=" + result.size()); 
            
            System.out.println("done.");
        }
        
        private static class FindJavaVisitor extends SimpleFileVisitor<Path>{
            private List<Path> result;
            public FindJavaVisitor(List<Path> result){
                this.result = result;
            }
            
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs){
                String filePath = file.toFile().getAbsolutePath();       
                if(filePath.matches(".*_[1|2]{1}\.(?i)(jpg|jpeg|gif|bmp|png)")){
                    try {
                        Files.deleteIfExists(file);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                  result.add(file.getFileName());
                } return FileVisitResult.CONTINUE;
            }
        }
    复制代码

    将目录下面所有符合条件的图片删除掉:filePath.matches(".*_[1|2]{1}\.(?i)(jpg|jpeg|gif|bmp|png)")

    复制代码
        public static void main(String[] args) throws IOException {
            Path startingDir = Paths.get("F:\111111\upload\images");    // F:111111\upload\images\2\20141206
            List<Path> result = new LinkedList<Path>();
            Files.walkFileTree(startingDir, new FindJavaVisitor(result));
            System.out.println("result.size()=" + result.size()); 
            
            System.out.println("done.");
        }
        
        private static class FindJavaVisitor extends SimpleFileVisitor<Path>{
            private List<Path> result;
            public FindJavaVisitor(List<Path> result){
                this.result = result;
            }
            
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs){
                String filePath = file.toFile().getAbsolutePath();
                int width = 224;
                int height = 300;
                StringUtils.substringBeforeLast(filePath, ".");
                String newPath = StringUtils.substringBeforeLast(filePath, ".") + "_1." 
                                                + StringUtils.substringAfterLast(filePath, ".");
                try {
                    ImageUtil.zoomImage(filePath, newPath, width, height);
                } catch (IOException e) {
                    e.printStackTrace();
                    return FileVisitResult.CONTINUE;
                }
                result.add(file.getFileName());
                return FileVisitResult.CONTINUE;
            }
        }
    复制代码

    为目录下的所有图片生成指定大小的缩略图。a.jpg 则生成 a_1.jpg

    2. 强大的java.nio.file.Files

    1)创建目录和文件:

    复制代码
            try {
                Files.createDirectories(Paths.get("C://TEST"));
                if(!Files.exists(Paths.get("C://TEST")))
                        Files.createFile(Paths.get("C://TEST/test.txt"));
    //            Files.createDirectories(Paths.get("C://TEST/test2.txt"));
            } catch (IOException e) {
                e.printStackTrace();
            }
    复制代码

    注意创建目录和文件Files.createDirectories 和 Files.createFile不能混用,必须先有目录,才能在目录中创建文件。

    2)文件复制:

    从文件复制到文件:Files.copy(Path source, Path target, CopyOption options);

    从输入流复制到文件:Files.copy(InputStream in, Path target, CopyOption options);

    从文件复制到输出流:Files.copy(Path source, OutputStream out);

    复制代码
            try {
                Files.createDirectories(Paths.get("C://TEST"));
                if(!Files.exists(Paths.get("C://TEST")))
                        Files.createFile(Paths.get("C://TEST/test.txt"));
    //          Files.createDirectories(Paths.get("C://TEST/test2.txt"));
                Files.copy(Paths.get("C://my.ini"), System.out);
                Files.copy(Paths.get("C://my.ini"), Paths.get("C://my2.ini"), StandardCopyOption.REPLACE_EXISTING);
                Files.copy(System.in, Paths.get("C://my3.ini"), StandardCopyOption.REPLACE_EXISTING);
            } catch (IOException e) {
                e.printStackTrace();
            }
    复制代码

    3)遍历一个目录和文件夹上面已经介绍了:Files.newDirectoryStream , Files.walkFileTree

    4)读取文件属性:

                Path zip = Paths.get(uri);
                System.out.println(Files.getLastModifiedTime(zip));
                System.out.println(Files.size(zip));
                System.out.println(Files.isSymbolicLink(zip));
                System.out.println(Files.isDirectory(zip));
                System.out.println(Files.readAttributes(zip, "*"));

    5)读取和设置文件权限:

    复制代码
                Path profile = Paths.get("/home/digdeep/.profile");
                PosixFileAttributes attrs = Files.readAttributes(profile, PosixFileAttributes.class);// 读取文件的权限
                Set<PosixFilePermission> posixPermissions = attrs.permissions();
                posixPermissions.clear();
                String owner = attrs.owner().getName();
                String perms = PosixFilePermissions.toString(posixPermissions);
                System.out.format("%s %s%n", owner, perms);
                
                posixPermissions.add(PosixFilePermission.OWNER_READ);
                posixPermissions.add(PosixFilePermission.GROUP_READ);
                posixPermissions.add(PosixFilePermission.OTHERS_READ);
                posixPermissions.add(PosixFilePermission.OWNER_WRITE);
                
                Files.setPosixFilePermissions(profile, posixPermissions);    // 设置文件的权限
    复制代码

    Files类简直强大的一塌糊涂,几乎所有文件和目录的相关属性,操作都有想要的api来支持。这里懒得再继续介绍了,详细参见 jdk8 的文档。

    一个实际例子:

    复制代码
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.nio.charset.StandardCharsets;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    public class StringTools {
        public static void main(String[] args) {
            try {
                BufferedReader reader = Files.newBufferedReader(Paths.get("C:\Members.sql"), StandardCharsets.UTF_8);
                BufferedWriter writer = Files.newBufferedWriter(Paths.get("C:\Members3.txt"), StandardCharsets.UTF_8);
    
                String str = null;
                while ((str = reader.readLine()) != null) {
                    if (str != null && str.indexOf(", CAST(0x") != -1 && str.indexOf("AS DateTime)") != -1) {
                        String newStr = str.substring(0, str.indexOf(", CAST(0x")) + ")";
                        writer.write(newStr);
                        writer.newLine();
                    }
                }
                writer.flush();
                writer.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    复制代码

    场景是,sql server导出数据时,会将 datatime 导成16进制的binary格式,形如:, CAST(0x0000A2A500FC2E4F AS DateTime))

    所以上面的程序是将最后一个 datatime 字段导出的 , CAST(0x0000A2A500FC2E4F AS DateTime) 删除掉,生成新的不含有datetime字段值的sql 脚本。用来导入到mysql中。

    做到半途,其实有更好的方法,使用sql yog可以很灵活的将sql server中的表以及数据导入到mysql中。使用sql server自带的导出数据的功能,反而不好处理。

  • 相关阅读:
    排序之快速排序
    希尔排序
    大数据的乘法
    大数据的乘法实现——C语言
    js函数纪实
    【转】js中$含义及用法
    python基础操作
    git 常用指令
    Django框架学习记录
    【转】Java 字符串拼接 五种方法的性能比较分析 从执行100次到90万次
  • 原文地址:https://www.cnblogs.com/jmsjh/p/7823542.html
Copyright © 2020-2023  润新知