java IO操作知识点

 IO流的概念:

  • IO流,将不同的输入输出,以相同的方式操作read(),write();创建不同类型的流,有不同的实现方式,不同类型的流,又有各自特有的操作方式。
  • 无论内部如何工作,所有IO流呈现的都是相同的,简单的模式,程序中流入或流出的一系列数据。

Inputstream、Outputstream:

  • 输入流,输出流的操作超类,支持子类以基本字节的方式操作二进制数据
  • java.io.InputStream抽象类:基本子类,ByteArrayInputStream,FileInputStream等; 
  • int read() throws IOException,抽象方法由具体子类实现,返回流中下一字节(必然是0-255之间的整数表示),如果到达流末没有可读字节,返回-1.
  • java.io.OutputStream抽象类:基本子类,ByteArrayOutputStream,FileOutputStream等;
  • void write(int b) throws IOException 抽象方法。将十进制按字节写入输出流。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Paths;

public class TestIO {
    public static void main(String[] args) {
        try {
            getByteStreams();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    public static void getByteStreams()throws IOException {
        FileInputStream in=new FileInputStream("C:/Users/yu/Desktop/a.txt");
        FileOutputStream out=new FileOutputStream("C:/Users/yu/Desktop/b.txt");
        int c;
        while((c=in.read())!=-1){
            System.out.println("读取字节的10进制整数:"+c);
            out.write(c);
        }
        in.close();//有个问题就在于一旦异常了资源就无法关闭;
        out.close();
    }

}

资源对象的关闭:

  • 资源文件的关闭:资源文件,比如IO流不会像其他对象,因失去引用而自动释放占用的资源,因此,必须被正确的关闭,否则会导致内存的溢出,以IO流为例,为确保无论是否出现异常,资源均被关闭,应在finally块中手动关闭资源,但这样会让程序中有大量的冗余 ;

  • 解决办法:引入java.lang.AutoCloseable接口,任何实现AutoCloseable接口的类型,均是支持自动关闭的资源类型。然后采用try-with-resources,在try语句中,声明需要关闭的资源,从而保证,无论try块是否引发异常,资源在try块结束后自动关闭(Java7) ;

  • java.io.Closeable接口继承AutoCloseable接口。原全部需要手动调用close()方法关闭的资源,全部支持try-with-resources自动关闭。

    try-with-resources语句,极大的简化了资源处理代码,使开发者无需关心资源状态,无需关心资源对象的创建顺序,无需关心资源对象的正确关闭方式

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Paths;

public class TestIO {
    public static void main(String[] args) {
            getByteStreams();
    }
    public static void getByteStreams() {
        try (FileInputStream in = new FileInputStream("C:/Users/yu/Desktop/a.txt");
             FileOutputStream out = new FileOutputStream("C:/Users/yu/Desktop/b.txt");) {
            int c;
            while ((c = in.read()) != -1) {
                System.out.println("读取字节的10进制整数:" + c);
                out.write(c);
            }
            in.close();//有个问题就在于一旦异常了资源就无法关闭;
            out.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
  • 注意:

    (1)资源的自动关闭,与异常无关。异常改怎么处理依然怎么处理。

    (2)在try语句中声明使用资源后,执行顺序:

    • ​​​​无异常,在try块执行后,自动关闭资源,finally块

    • 有异常,自动关闭资源,catch块,finally块

基于字符数组缓冲区的IO操作处理:

  • 前面说的基于单字节的基本read()/write()方法,仅用于理解IO流执行过程,实际开发不会使用。用的是基于字节数组缓冲区的IO操作方法:
  • int read(byte[] b),InputStream中声明的方法,将流中字节读取到字节数组b中,第1个字节置入数组0位置…,直到读取到数组b长度的字节位置为止;返回读取的字节长度;如果没有可读字节,返回-1。

  • write(byte[] b, int off, int len),OutputStream中声明的方法,从字节数组b,off位置开始读取,至长度len结束;
  • import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.nio.file.Paths;
    
    public class TestIO {
        public static void main(String[] args) {
                getByteStreams();
        }
        public static void getByteStreams() {
            try (FileInputStream in = new FileInputStream("C:/Users/yu/Desktop/a.txt");
                 FileOutputStream out = new FileOutputStream("C:/Users/yu/Desktop/b.txt");) {
                byte []buffer=new byte[2];
                int len=0;
                while((len=in.read(buffer))!=-1){
                    out.write(buffer,0,len);
                }
                in.close();//有个问题就在于一旦异常了资源就无法关闭;
                out.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    }
    

路径:

  • 绝对路径,始终包含根元素和查找文件所需的完整目录列表。 例如,D:/test/a.txt。找到文件所需的所有信息都包含在路径声明中

    相对路径,例如,a.txt。没有更多信息,程序将无法访问。即,相对路径,最终也必须基于绝对路径描述。

  • 为什么用NIO:

    Java.io.File类,包含耦合了文件路径声明,以及文件操作方法的类;且是同步阻塞的

    NIO2 (java8),将文件路径与文件操作,分离;且支持异步非阻塞

    java.nio.file.Path接口,表示系统文件/目录的绝对的/相对的路径

    java.nio.file.Files工具类,包含处理文件操作的方法,包括文件的,创建,删除,复制,移动等

  • Path接口:Path代表一个不依赖于系统的文件路径。即运行在不同操作系统下,Path的具体实现不同(windows/linux),但开发者仅需面向Path描述路径,不同系统,而无需关心操作系统差异。

  • Path get(String path):最常用的方法,把转换路径字符串转为Path对象。

  • Path定义了许多获取文件数据信息的方法及路径的拼接方法:

    Path getFileName(),返回文件名或名称元素序列的最后一个元素。即,最后一个路径描述,可能是文件名也可能是目录名

    Path getParent(),返回父目录的路径

    Path getRoot(),返回路径的根

    Path resolve(Path other)方法,将路径拼接为一个新路径

    boolean equals(Object obj):重写了equals判断路径是否相同

  •  
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    public class TestIO {
        public static void main(String[] args) {
                Path p= Paths.get("C:/Users/yu/Desktop");
                Path p1=Paths.get("a.txt");
            System.out.println(p.getClass().getName());//Path是一个接口输出实现类的名字
            System.out.println(p);
            System.out.println(p.getFileName());//返回文件名或名称元素序列的最后一个元素。即,最后一个路径描述,可能是文件名也可能是目录名
            System.out.println(p.getParent());//返回父目录的路径
            System.out.println(p.getRoot());//返回路径的根
            p.resolve(p1);//将路径拼接为一个新路径
            p.equals(p1);//重写了equals判断路径是否相同
    
        }
    
    }
    

Files工具类:

  • java.nio.file.Files工具类,提供了丰富的基于Path操作的静态方法,读取/写入/操作,文件与目录。方法分类:

  •  文件或目录的判断:

    boolean exists(Path path)/notExists(Path path),Path路径是否存在

    Boolean isDirectory(Path path),path是否为目录

  • 文件或目录的创建:

    Path createDirectory(Path dir) throws IOException。目录路径已存在则异常;目录路径为多级目录,异常

    Path createDirectories(Path dir) throws IOException。自动创建多级不存在目录;目录已存在,无异常

    Path createFile(path) throws IOException。基于指定路径,创建文件。文件存在,异常

  • 文件或目录的复制:

    Path copy(Path source, Path target, CopyOption... options) throws IOException,将文件复制到目标文件。默认,如果文件已经存在,异常

    如果source为目录,不会复制里面的文件,仅相当于创建一个空目录

    java.nio.file.StandardCopyOption枚举,实现了CopyOption接口,复制选项

  • 文件或目录的移动:

    Path move(Path source, Path target, CopyOption... options) throws IOException,将文件移动或重命名为目标文件。

    默认,如果目标文件存在,则异常,可通过options参数声明移动选项

    如果在本目录下移动,相当于文件改名

  • 文件或目录的删除:

    void delete(Path path) throws IOException。删除指定路径;路径不存在,异常

    boolean deleteIfExists(Path path) throws IOException。路径不存在,不删除。返回是否删除成功

    如果路径为目录,目录中包含文件(即不为空),2种删除均异常

  •  指定路径的遍历(Files的方法):

    Stream<Path> walk(Path start, int maxDepth) throws IOException:遍历,基于指定深度遍历path路径中的目录和文件

    Stream<Path> walk(Path start) throws IOException:遍历path路径中的所有目录和文件,包括子目录的,观察遍历时的输出顺序,按层次输出的。注意返回值是流,后面可以用流的操作,比如过滤,排序等功能。可以借助于此方法删除非空目录

  • import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.nio.file.StandardCopyOption;
    import java.util.function.Consumer;
    
    public class TestIO {
        public static void main(String[] args) {
            try {
                path();
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
        public static void path() throws IOException {
            Path p= Paths.get("C:/Users/yu/Desktop");
            Path p1=Paths.get("a.txt");
            Path p2=Paths.get("C:/Users/yu/Desktop/b.txt");
            Path p3=Paths.get("C:/Users/yu/Desktop/a.txt");
    //        System.out.println(Files.exists(p));//Path路径是否存在
    //        System.out.println(Files.isDirectory(p));//path是否为目录
    //        System.out.println(Files.createDirectory(p));//目录的创建,目录路径已存在则异常;目录路径为多级目录,异常
    //        System.out.println(Files.createDirectories(p));//目录的创建,自动创建多级不存在目录;目录已存在,无异常
    //        System.out.println(Files.createFile(p2));//文件的创建,基于指定路径,创建文件。文件存在,异常;
    //        Files.copy(p2,p3, StandardCopyOption.REPLACE_EXISTING);/*将文件复制到目标文件。默认,如果文件已经存在,异常
    //        如果source为目录,不会复制里面的文件,仅相当于创建一个空目录
    //        java.nio.file.StandardCopyOption枚举,实现了CopyOption接口,复制选项*/
    //        Files.move(p2,p3,StandardCopyOption.REPLACE_EXISTING)/*将文件移动或重命名为目标文件。
    //           默认,如果目标文件存在,则异常,可通过options参数声明移动选项
    //           如果在本目录下移动,相当于文件改名*/
    //        Files.delete(p2);/*路径不存在,不删除。返回是否删除成功
    //如果路径为目录,目录中包含文件(即不为空),2种删除均异常*/
    
            Files.walk(p3).forEach(System.out::println);
        }
    }
    

猜你喜欢

转载自blog.csdn.net/qq_56350439/article/details/124541797