一文带你深入理解【Java基础】· IO流(下)

写在前面


        Hello大家好, 我是【麟-小白】,一位软件工程专业的学生,喜好计算机知识。希望大家能够一起学习进步呀!本人是一名在读大学生,专业水平有限,如发现错误不足之处,请多多指正!谢谢大家!!!

        如果小哥哥小姐姐们对我的文章感兴趣,请不要吝啬你们的小手,多多点赞加关注呀!❤❤❤ 爱你们!!!


目录

写在前面

1. 对象流

1.1 对象流概述

1.2 对象的序列化

1.3 使用对象流序列化对象

1.4 面试题

1.5 对象流代码演示

 2. 随机存取文件流

2.1 RandomAccessFile 类

2.2 读取文件内容

2.3 写入文件内容

2.4 流的基本应用小节

2.5 随机存取文件流代码演示

3. NIO.2中Path、Paths、Files类的使用

3.1 Java NIO 概述

3.2 Path、Paths和Files核心API

3.3 Path接口

3.4 Files 类

3.5 NIO.2中Path、Paths、Files类的代码演示

3.5.1 Files工具类的使用

3.5.2 Path类的使用

结语


【往期回顾】

一文带你深入理解【Java基础】· IO流(中)

一文带你深入理解【Java基础】· IO流(上)

一文带你深入理解【Java基础】· 泛型

一文带你深入理解【Java基础】· Java集合(上)

一文带你深入理解【Java基础】· 注解

一文带你深入理解【Java基础】· 枚举类


1. 对象流


1.1 对象流概述

  • ObjectInputStreamOjbectOutputSteam
    • 用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
  • 序列化:ObjectOutputStream保存基本类型数据或对象的机制
  • 反序列化:ObjectInputStream读取基本类型数据或对象的机制
  • ObjectOutputStreamObjectInputStream不能序列化statictransient修饰的成员变量

1.2 对象的序列化

  • 对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。//当其它程序获取了这种二进制流,就可以恢复成原来的Java对象
  • 序列化的好处在于可将任何实现了Serializable接口的对象转化为字节数据,使其在保存和传输时可被还原
  • 序列化是 RMIRemote Method Invoke – 远程方法调用)过程的参数和返回值都必须实现的机制,而 RMI JavaEE 的基础。因此序列化机制是JavaEE 平台的基础
  • 如果需要让某个对象支持序列化机制,则必须让对象所属的类及其属性是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一。否则,会抛出NotSerializableException异常
    • Serializable
    • Externalizable
  • 凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:
    • private static final long serialVersionUID;
    • serialVersionUID用来表明类的不同版本间的兼容性。简言之,其目的是以序列化对象进行版本控制,有关各版本反序列化时是否兼容。
    • 如果类没有显示定义这个静态常量,它的值是Java运行时环境根据类的内部细节自动生成的。若类的实例变量做了修改,serialVersionUID 可能发生变化。故建议,显式声明。
  • 简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException)

1.3 使用对象流序列化对象

若某个类实现了 Serializable 接口,该类的对象就是可序列化的:
  • 创建一个 ObjectOutputStream
  • 调用 ObjectOutputStream 对象的 writeObject(对象) 方法输出可序列化对象
  • 注意写出一次,操作flush()一次
反序列化
  • 创建一个 ObjectInputStream
  • 调用 readObject() 方法读取流中的对象
强调:
  • 如果某个类的属性不是基本数据类型或 String 类型,而是另一个引用类型,那么这个引用类型必须是可序列化的,否则拥有该类型Field 的类也不能序列化
  • //序列化:将对象写入到磁盘或者进行网络传输。
  • //要求对象必须实现序列化

  • //反序列化:将磁盘中的对象数据源读出。 

1.4 面试题

谈谈你对 java.io.Serializable 接口的理解,我们知道它用于序列化, 是空方法接口,还有其它认识吗?
  • 实现了Serializable接口的对象,可将它们转换成一系列字节,并可在以后完全恢复回原来的样子。这一过程亦可通过网络进行。这意味着序列化机制能自动补偿操作系统间的差异。换句话说,可以先在Windows机器上创建一个对象,对其序列化,然后通过网络发给一台Unix机器,然后在那里准确无误地重新“装配”。不必关心数据在不同机器上如何表示,也不必关心字节的顺序或者其他任何细节。
  • 由于大部分作为参数的类如String、Integer等都实现了java.io.Serializable的接口,也可以利用多态的性质,作为参数使接口更灵活。

1.5 对象流代码演示

import org.junit.Test;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;

/**
 * 对象流的使用
 * 1.ObjectInputStream 和 ObjectOutputStream
 * 2.作用:用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
 *
 * 3.要想一个java对象是可序列化的,需要满足相应的要求。见Person.java
 *
 * 4.序列化机制:
 * 对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种
 * 二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。
 * 当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。
 * @author 麟-小白
 */
public class ObjectInputOutputStreamTest {
    /**
     序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去
     使用ObjectOutputStream实现
     */
    @Test
    public void testObjectOutputStream() {
        ObjectOutputStream oos = null;
        try {
            //1.
            oos = new ObjectOutputStream(Files.newOutputStream(Paths.get("object.dat")));
            //2.
            oos.writeObject("我爱北京天安门");
            oos.flush();//刷新操作

            oos.writeObject(new Person("王铭", 23));
            oos.flush();

            oos.writeObject(new Person("张学良", 23, 1001, new Account(5000)));
            oos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (oos != null) {
                //3.
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     反序列化:将磁盘文件中的对象还原为内存中的一个java对象
     使用ObjectInputStream来实现
     */
    @Test
    public void testObjectInputStream() {
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(Files.newInputStream(Paths.get("object.dat")));
            Object obj = ois.readObject();
            String str = (String) obj;
            Person p = (Person) ois.readObject();
            Person p1 = (Person) ois.readObject();
            System.out.println(str);
            System.out.println(p);
            System.out.println(p1);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (ois != null) {
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
import java.io.Serializable;

/**
 * Person需要满足如下的要求,方可序列化
 * 1.需要实现接口:Serializable
 * 2.当前类提供一个全局常量:serialVersionUID
 * 3.除了当前Person类需要实现Serializable接口之外,还必须保证其内部所有属性
 *   也必须是可序列化的。(默认情况下,基本数据类型可序列化)
 * 补充:ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量
 * @author 麟-小白
 */
public class Person implements Serializable {
    public static final long serialVersionUID = 475463534532L;
    private String name;
    private int age;
    private int id;
    private Account acct;

    public Person(String name, int age, int id) {
        this.name = name;
        this.age = age;
        this.id = id;
    }

    public Person(String name, int age, int id, Account acct) {
        this.name = name;
        this.age = age;
        this.id = id;
        this.acct = acct;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", id=" + id +
                ", acct=" + acct +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person() {

    }
}

class Account implements Serializable {
    public static final long serialVersionUID = 4754534532L;
    private double balance;

    @Override
    public String toString() {
        return "Account{" +
                "balance=" + balance +
                '}';
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    public Account(double balance) {
        this.balance = balance;
    }
}
 

 2. 随机存取文件流


2.1 RandomAccessFile

  • RandomAccessFile 声明在java.io包下,但直接继承于java.lang.Object类。并且它实现了DataInputDataOutput这两个接口,也就意味着这个类既可以读也可以写。
  • RandomAccessFile 类支持 随机访问的方式,程序可以直接跳到文件的任意地方来读、写文件
    • 支持只访问文件的部分内容
    • 可以向已存在的文件后追加内容
  • RandomAccessFile 对象包含一个记录指针,用以标示当前读写处的位置。
  • RandomAccessFile 类对象可以自由移动记录指针:
    • long getFilePointer()获取文件记录指针的当前位置
    • void seek(long pos):将文件记录指针定位到 pos 位置

构造器

  • public RandomAccessFile(File file, String mode)
  • public RandomAccessFile(String name, String mode)

创建 RandomAccessFile 类实例需要指定一个 mode 参数,该参数指定 RandomAccessFile 的访问模式:

  • r: 以只读方式打开
  • rw:打开以便读取和写入
  • rwd:打开以便读取和写入;同步文件内容的更新
  • rws:打开以便读取和写入;同步文件内容和元数据的更新

如果模式为只读r。则不会创建文件,而是会去读取一个已经存在的文件,如果读取的文件不存在则会出现异常。 如果模式为rw读写。如果文件不存在则会去创建文件,如果存在则不会创建。我们可以用RandomAccessFile这个类,来实现一个多线程断点下载的功能,用过下载工具的朋友们都知道,下载前都会建立两个临时文件,一个是与被下载文件大小相同的空文件,另一个是记录文件指针的位置文件,每次暂停的时候,都会保存上一次的指针,然后断点下载的时候,会继续从上一次的地方下载,从而实现断点下载或上传的功能,有兴趣的朋友们可以自己实现下。


2.2 读取文件内容


2.3 写入文件内容


2.4 流的基本应用小节

  • 流是用来处理数据的。
  • 处理数据时,一定要先明确数据源,与数据目的地
  • 数据源可以是文件,可以是键盘。
  • 数据目的地可以是文件、显示器或者其他设备。
  • 而流只是在帮助数据进行传输,并对传输的数据进行处理,比如过滤处理、转换处理等。

2.5 随机存取文件流代码演示

import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * RandomAccessFile的使用
 * 1.RandomAccessFile直接继承于java.lang.Object类,实现了DataInput和DataOutput接口
 * 2.RandomAccessFile既可以作为一个输入流,又可以作为一个输出流
 * 3.如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建。
 *   如果写出到的文件存在,则会对原有文件内容进行覆盖。(默认情况下,从头覆盖)
 * 4. 可以通过相关的操作,实现RandomAccessFile“插入”数据的效果
 * @author 麟-小白
 */
public class RandomAccessFileTest {
    @Test
    public void test1() {
        RandomAccessFile raf1 = null;
        RandomAccessFile raf2 = null;
        try {
            //1.
            raf1 = new RandomAccessFile(new File("爱情与友情.jpg"), "r");
            raf2 = new RandomAccessFile(new File("爱情与友情1.jpg"), "rw");
            //2.
            byte[] buffer = new byte[1024];
            int len;
            while ((len = raf1.read(buffer)) != -1) {
                raf2.write(buffer, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //3.
            if (raf1 != null) {
                try {
                    raf1.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (raf2 != null) {
                try {
                    raf2.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Test
    public void test2() throws IOException {
        RandomAccessFile raf1 = new RandomAccessFile("hello.txt", "rw");
        //将指针调到角标为3的位置
        raf1.seek(3);
        raf1.write("xyz".getBytes());
        raf1.close();
    }

    /**
     使用RandomAccessFile实现数据的插入效果
     */
    @Test
    public void test3() throws IOException {
        RandomAccessFile raf1 = new RandomAccessFile("hello.txt", "rw");
        //将指针调到角标为3的位置
        raf1.seek(3);
        //保存指针3后面的所有数据到StringBuilder中
        StringBuilder builder = new StringBuilder((int) new File("hello.txt").length());
        byte[] buffer = new byte[20];
        int len;
        while ((len = raf1.read(buffer)) != -1) {
            builder.append(new String(buffer, 0, len));
        }
        //调回指针,写入“xyz”
        raf1.seek(3);
        raf1.write("xyz".getBytes());
        //将StringBuilder中的数据写入到文件中
        raf1.write(builder.toString().getBytes());
        raf1.close();
        //思考:将StringBuilder替换为ByteArrayOutputStream
    }
}

3. NIO.2PathPathsFiles类的使用


3.1 Java NIO 概述

  • Java NIO (New IONon-Blocking IO)是从Java 1.4版本开始引入的一套新的IO API,可以替代标准的Java IO APINIO与原来的IO有同样的作用和目的,但是使用的方式完全不同,NIO支持面向缓冲区的(IO是面向流的)、基于通道的IO操作。NIO将以更加高效的方式进行文件的读写操作。
  • Java API中提供了两套NIO一套是针对标准输入输出NIO另一套就是网络编程NIO
  • java.nio.channels.Channel
    • FileChannel:处理本地文件
    • SocketChannelTCP网络编程的客户端的Channel
    • ServerSocketChannel:TCP网络编程的服务器端的Channel
    • DatagramChannelUDP网络编程中发送端和接收端的Channel
NIO. 2
  • 随着 JDK 7 的发布,JavaNIO进行了极大的扩展,增强了对文件处理和文件系统特性的支持,以至于我们称他们为 NIO.2。因为 NIO 提供的一些功能,NIO已经成为文件处理中越来越重要的部分。

3.2 PathPathsFiles核心API

  • 早期的Java只提供了一个File类来访问文件系统,但File类的功能比较有限,所提供的方法性能也不高。而且,大多数方法在出错时仅返回失败,并不会提供异常信息。
  • NIO. 2为了弥补这种不足,引入了Path接口,代表一个平台无关的平台路径,描述了目录结构中文件的位置。Path可以看成是File类的升级版本,实际引用的资源也可以不存在。

在以前IO操作都是这样写的:

  • import java.io.File;
  • File file = new File("index.html");

但在Java7 中,我们可以这样写:

  • import java.nio.file.Path;
  • import java.nio.file.Paths;
  • Path path = Paths.get("index.html");

同时,NIO.2java.nio.file包下还提供了FilesPaths工具类,Files包含了大量静态的工具方法来操作文件;Paths则包含了两个返回Path的静态工厂方法。

Paths 类提供的静态 get() 方法用来获取 Path 对象:

  • static Path get(String first, String … more) : 用于将多个字符串串连成路径
  • static Path get(URI uri): 返回指定uri对应的Path路径

3.3 Path接口

Path 常用方法:
  • String toString() : 返回调用 Path 对象的字符串表示形式
  • boolean startsWith(String path) : 判断是否以 path 路径开始
  • boolean endsWith(String path) : 判断是否以 path 路径结束
  • boolean isAbsolute() : 判断是否是绝对路径
  • Path getParent() :返回Path对象包含整个路径,不包含 Path 对象指定的文件路径
  • Path getRoot() :返回调用 Path 对象的根路径
  • Path getFileName() : 返回与调用 Path 对象关联的文件名
  • int getNameCount() : 返回Path 根目录后面元素的数量
  • Path getName(int idx) : 返回指定索引位置 idx 的路径名称
  • Path toAbsolutePath() : 作为绝对路径返回调用 Path 对象
  • Path resolve(Path p) :合并两个路径,返回合并后的路径对应的Path对象
  • File toFile(): Path转化为File类的对象

3.4 Files

j ava.nio.file.Files 用于操作文件或目录的工具类。
Files 常用方法:
  • Path copy(Path src, Path dest, CopyOption … how) : 文件的复制
  • Path createDirectory(Path path, FileAttribute<?> … attr) : 创建一个目录
  • Path createFile(Path path, FileAttribute<?> … arr) : 创建一个文件
  • void delete(Path path) : 删除一个文件/目录,如果不存在,执行报错
  • void deleteIfExists(Path path) : Path对应的文件/目录如果存在,执行删除
  • Path move(Path src, Path dest, CopyOption…how) : src 移动到 dest 位置
  • long size(Path path) : 返回 path 指定文件的大小
Files 常用方法:用于判断
  • boolean exists(Path path, LinkOption … opts) : 判断文件是否存在
  • boolean isDirectory(Path path, LinkOption … opts) : 判断是否是目录
  • boolean isRegularFile(Path path, LinkOption … opts) : 判断是否是文件
  • boolean isHidden(Path path) : 判断是否是隐藏文件
  • boolean isReadable(Path path) : 判断文件是否可读
  • boolean isWritable(Path path) : 判断文件是否可写
  • boolean notExists(Path path, LinkOption … opts) : 判断文件是否不存在
Files 常用方法:用于操作内容
  • SeekableByteChannel newByteChannel(Path path, OpenOption…how) : 获取与指定文件的连接,how 指定打开方式。
  • DirectoryStream<Path> newDirectoryStream(Path path) : 打开 path 指定的目录
  • InputStream newInputStream(Path path, OpenOption…how):获取 InputStream 对象
  • OutputStream newOutputStream(Path path, OpenOption…how) : 获取 OutputStream 对象

3.5 NIO.2PathPathsFiles类的代码演示

3.5.1 Files工具类的使用

import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.*;
import java.util.Iterator;

/**
 * Files工具类的使用:操作文件或目录的工具类
 * @author 麟-小白
 */
public class FilesTest {
    @Test
    public void test1() throws IOException {
        Path path1 = Paths.get("d:\\nio", "hello.txt");
        Path path2 = Paths.get("atguigu.txt");
//		Path copy(Path src, Path dest, CopyOption … how) : 文件的复制
//      要想复制成功,要求path1对应的物理上的文件存在。path1对应的文件没有要求。
//		Files.copy(path1, path2, StandardCopyOption.REPLACE_EXISTING);

//		Path createDirectory(Path path, FileAttribute<?> … attr) : 创建一个目录
//      要想执行成功,要求path对应的物理上的文件目录不存在。一旦存在,抛出异常。
        Path path3 = Paths.get("d:\\nio\\nio1");
//		Files.createDirectory(path3);

//		Path createFile(Path path, FileAttribute<?> … arr) : 创建一个文件
//      要想执行成功,要求path对应的物理上的文件不存在。一旦存在,抛出异常。
        Path path4 = Paths.get("d:\\nio\\hi.txt");
//		Files.createFile(path4);

//		void delete(Path path) : 删除一个文件/目录,如果不存在,执行报错
//		Files.delete(path4);

//		void deleteIfExists(Path path) : Path对应的文件/目录如果存在,执行删除.如果不存在,正常执行结束
        Files.deleteIfExists(path3);

//		Path move(Path src, Path dest, CopyOption…how) : 将 src 移动到 dest 位置
        //要想执行成功,src对应的物理上的文件需要存在,dest对应的文件没有要求。
//		Files.move(path1, path2, StandardCopyOption.ATOMIC_MOVE);

//		long size(Path path) : 返回 path 指定文件的大小
        long size = Files.size(path2);
        System.out.println(size);
    }

    @Test
    public void test2() throws IOException {
        Path path1 = Paths.get("d:\\nio", "hello.txt");
        Path path2 = Paths.get("atguigu.txt");
//		boolean exists(Path path, LinkOption … opts) : 判断文件是否存在
        System.out.println(Files.exists(path2, LinkOption.NOFOLLOW_LINKS));

//		boolean isDirectory(Path path, LinkOption … opts) : 判断是否是目录
        //不要求此path对应的物理文件存在。
        System.out.println(Files.isDirectory(path1, LinkOption.NOFOLLOW_LINKS));

//		boolean isRegularFile(Path path, LinkOption … opts) : 判断是否是文件

//		boolean isHidden(Path path) : 判断是否是隐藏文件
        //要求此path对应的物理上的文件需要存在。才可判断是否隐藏。否则,抛异常。
//		System.out.println(Files.isHidden(path1));

//		boolean isReadable(Path path) : 判断文件是否可读
        System.out.println(Files.isReadable(path1));
//		boolean isWritable(Path path) : 判断文件是否可写
        System.out.println(Files.isWritable(path1));
//		boolean notExists(Path path, LinkOption … opts) : 判断文件是否不存在
        System.out.println(Files.notExists(path1, LinkOption.NOFOLLOW_LINKS));
    }

    /**
     * StandardOpenOption.READ:表示对应的Channel是可读的。
     * StandardOpenOption.WRITE:表示对应的Channel是可写的。
     * StandardOpenOption.CREATE:如果要写出的文件不存在,则创建。如果存在,忽略
     * StandardOpenOption.CREATE_NEW:如果要写出的文件不存在,则创建。如果存在,抛异常
     * @author 麟-小白
     * @throws IOException
     */
    @Test
    public void test3() throws IOException {
        Path path1 = Paths.get("d:\\nio", "hello.txt");

//		InputStream newInputStream(Path path, OpenOption…how):获取 InputStream 对象
        InputStream inputStream = Files.newInputStream(path1, StandardOpenOption.READ);

//		OutputStream newOutputStream(Path path, OpenOption…how) : 获取 OutputStream 对象
        OutputStream outputStream = Files.newOutputStream(path1, StandardOpenOption.WRITE, StandardOpenOption.CREATE);

//		SeekableByteChannel newByteChannel(Path path, OpenOption…how) : 获取与指定文件的连接,how 指定打开方式。
        SeekableByteChannel channel = Files.newByteChannel(path1, StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);

//		DirectoryStream<Path>  newDirectoryStream(Path path) : 打开 path 指定的目录
        Path path2 = Paths.get("e:\\teach");
        DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path2);
        Iterator<Path> iterator = directoryStream.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

3.5.2 Path类的使用

import org.junit.Test;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * 1. jdk 7.0 时,引入了 Path、Paths、Files三个类。
 * 2.此三个类声明在:java.nio.file包下。
 * 3.Path可以看做是java.io.File类的升级版本。也可以表示文件或文件目录,与平台无关
 * 4.如何实例化Path:使用Paths.
 * static Path get(String first, String … more) : 用于将多个字符串串连成路径
 * static Path get(URI uri): 返回指定uri对应的Path路径
 * @author 麟-小白
 */
public class PathTest {
    /** 如何使用Paths实例化Path */
    @Test
    public void test1() {
        //new File(String filepath)
        Path path1 = Paths.get("d:\\nio\\hello.txt");
        //new File(String parent,String filename);
        Path path2 = Paths.get("d:\\", "nio\\hello.txt");

        System.out.println(path1);
        System.out.println(path2);

        Path path3 = Paths.get("d:\\", "nio");
        System.out.println(path3);
    }

    /** Path中的常用方法 */
    @Test
    public void test2() {
        Path path1 = Paths.get("d:\\", "nio\\nio1\\nio2\\hello.txt");
        Path path2 = Paths.get("hello.txt");

//		String toString() : 返回调用 Path 对象的字符串表示形式
        System.out.println(path1);
//		boolean startsWith(String path) : 判断是否以 path 路径开始
        System.out.println(path1.startsWith("d:\\nio"));
//		boolean endsWith(String path) : 判断是否以 path 路径结束
        System.out.println(path1.endsWith("hello.txt"));
//		boolean isAbsolute() : 判断是否是绝对路径
        System.out.println(path1.isAbsolute() + "~");
        System.out.println(path2.isAbsolute() + "~");
//		Path getParent() :返回Path对象包含整个路径,不包含 Path 对象指定的文件路径
        System.out.println(path1.getParent());
        System.out.println(path2.getParent());
//		Path getRoot() :返回调用 Path 对象的根路径
        System.out.println(path1.getRoot());
        System.out.println(path2.getRoot());
//		Path getFileName() : 返回与调用 Path 对象关联的文件名
        System.out.println(path1.getFileName() + "~");
        System.out.println(path2.getFileName() + "~");
//		int getNameCount() : 返回Path 根目录后面元素的数量
//		Path getName(int idx) : 返回指定索引位置 idx 的路径名称
        for (int i = 0; i < path1.getNameCount(); i++) {
            System.out.println(path1.getName(i) + "*****");
        }
//		Path toAbsolutePath() : 作为绝对路径返回调用 Path 对象
        System.out.println(path1.toAbsolutePath());
        System.out.println(path2.toAbsolutePath());
//		Path resolve(Path p) :合并两个路径,返回合并后的路径对应的Path对象
        Path path3 = Paths.get("d:\\", "nio");
        Path path4 = Paths.get("nioo\\hi.txt");
        path3 = path3.resolve(path4);
        System.out.println(path3);
//		File toFile(): 将Path转化为File类的对象
        //Path--->File的转换
        File file = path1.toFile();
        //File--->Path的转换
        Path newPath = file.toPath();
        System.out.println(newPath);
    }
}

结语


本人会持续更新文章的哦!希望大家一键三连,你们的鼓励就是作者不断更新的动力

猜你喜欢

转载自blog.csdn.net/qq_34025246/article/details/128353839