12. IO流
12.1 File类的使用
-
构造器:
File类对象可以是文件,也可以是目录
-
public File(String pathname)
以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果pathname是相对路径,则默认的当前路径在系统属性user.dir中存储- 绝对路径: 是一个固定的路径,从盘符开始
- 相对路径: 是相对于某个位置开始
File file = new File("hello.txt"); //注意:如果你创建文件或者文件目录没有写盘符路径, 那么默认在项目路径下
-
public File(String parent,String child)
以parent为父路径, child为子路径创建File对象File file1 = new File("E:", "aaa");
-
public File(File parent,String child)
根据一个父File对象和子文件路径创建File对象File file2 = new File(file, "bbb.txt");
注意:此时都没有考虑在硬盘中真实存在这些文件,只是生成内存层面的对象而已
-
-
路径分隔符:
-
路径中的每级目录之间用一个路径分隔符隔开
-
路径分隔符和系统有关:
- windows和DOS系统默认使用“\”来表示
- UNIX和URL使用“/”来表示
- Java程序支持跨平台运行,因此路径分隔符要慎用
-
为了解决这个隐患, File类提供了一个常量:
public static final String separator。根据操作系统,动态的提供分隔符File file = new File("hello.txt");//相对路径 File file1 = new File("E:\\1_课件\\dbcp.txt");//绝对路径 windows File file2 = new File("E:/1_课件/dbcp.txt");//Unix和URL File file3 = new File("E:"+File.separator+"1_课件"+File.separator+"dbcp.txt");//通用
-
-
常用方法:
-
File类的获取功能
-
String getAbsolutePath()
: 获取绝对路径 -
String getPath()
: 获取路径 -
String getName()
: 获取名称 -
String getParent()
: 获取上层文件目录路径,若无,返回null -
long length()
: 获取文件长度(即:字节数),不能获取目录的长度。 -
long lastModified()
: 获取最后一次的修改时间, 毫秒值 -
String[] list()
: 获取指定目录下的所有文件或者文件目录的名称数组File file = new File("D:\\DriverGenius"); String[] list = file.list(); for (String s:list ) { System.out.println(s); } //kadblock kcdpt kplanet ksoft log
-
File[] listFiles()
: 获取指定目录下的所有文件或者文件目录的File数组File file = new File("D:\\DriverGenius"); File[] files = file.listFiles(); for (File f:files ) { System.out.println(f); } //D:\DriverGenius\kcdpt //D:\DriverGenius\kplanet //D:\DriverGenius\ksoft
-
-
File类的重命名功能
-
boolean renameTo(File dest)
:把文件重命名为指定的文件路径,file1移动到file2指定位置,且改名为指定名File file1 = new File("D:\\hi.txt"); File file2 = new File("D:\\hh.txt"); boolean b = file1.renameTo(file2);
要想返回true,需要file1一定是存在的,且file2不能存在(执行完file1会消失,如果再执行一次,会返回false)
-
-
File类的判断功能
-
boolean isDirectory()
: 判断是否是文件目录 -
boolean isFile()
: 判断是否是文件 -
boolean exists()
: 判断是否存在 -
boolean canRead()
: 判断是否可读 -
boolean canWrite()
: 判断是否可写 -
boolean isHidden()
: 判断是否隐藏
-
-
File类的创建功能
boolean createNewFile()
: 创建文件。 若文件存在, 则不创建, 返回falseboolean mkdir()
: 创建文件目录。 如果此文件目录存在, 就不创建了;如果此文件目录的上层目录不存在, 也不创建boolean mkdirs()
: 创建文件目录。 如果输入路径中上层文件目录不存在, 一并创建
-
File类的删除功能
boolean delete()
: 删除文件或者文件夹- 删除注意事项:
- Java中的删除不走回收站
- 要删除一个文件目录, 该文件目录内不能包含文件或者文件目录(空才能删)
-
并未涉及到写入或者读取文件内容的操作,这些操作需要使用IO流来完成
-
后续File类的对象会作为参数传递到流的构造器中,指明读取或写入的”终点“
-
12.2 IO流原理及流的分类
-
Java程序中,对于数据的输入/输出操作以“流(stream)” 的方式进行
-
Java IO 原理:
-
输入input: 读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中
-
输出output: 将程序(内存)数据输出到磁盘、光盘等存储设备中
-
-
流的分类:
-
按操作数据单位不同分为: 字节流(8bit-byte),字符流(16bit-char)
-
按数据流的流向不同分为: 输入流,输出流
-
按流的角色的不同分为: 节点流,处理流(已有流的外边包的一层,如加速作用)
-
流的**抽象基类**:
字节流 字符流 输入流 InputStream Reader 输出流 OutputStream Writer
-
-
IO流体系:
12.3 节点流(文件流-开发中使用少)
-
读入操作:
-
示例:
//1.实例化File对象,指明要操作的文件 //读入的文件一定要存在,否则FileNotFoundException File file1 = new File("D:\\hh.txt"); //2.提供具体的流 FileInputStream fileInputStream = new FileInputStream(file1); //3.数据的读入 //⭐read():返回下一个字符的byte,如果到达文件末尾,则返回-1 int read = fileInputStream.read(); while (read != -1){ System.out.print((char) read);//helloworld read = fileInputStream.read(); } //4.关闭流 fileInputStream.close();
-
一定要关闭流:
垃圾回收机制只回收JVM堆内存里的对象空间。对其他物理连接,比如数据库连接、输入流输出流、Socket连接无能为力
-
异常处理优化:为了保证流关闭的处理一定会被执行,不使用throws抛异常,而使用try/catch
FileInputStream fileInputStream = null; try { File file1 = new File("D:\\hh.txt"); fileInputStream = new FileInputStream(file1); int read = fileInputStream.read(); while (read != -1){ System.out.print((char) read);//helloworld read = fileInputStream.read(); } } catch (IOException e) { e.printStackTrace(); } finally { try { //一定会执行关闭操作 fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } }
-
使用FileReader优化:不再一个个字符读,改为一次性读入5个字符
FileReader fileReader = null; try { File file1 = new File("D:\\hh.txt"); fileReader = new FileReader(file1); char[] charsBuffer = new char[5]; //⭐read(char[] charsBuffer): //返回每次读入charsBuffer数组中的字符的个数,到达末尾返回-1 int read; while ((read = fileReader.read(charsBuffer)) != -1){ //错误写法: /*for (int i = 0; i < charsBuffer.length; i++) { System.out.print(charsBuffer[i]);//helloworld123ld //最后一次数组中存着:123ld }*/ //正确写法: for (int i = 0; i < read; i++) { //read:返回本次读入的字符的个数 System.out.print(charsBuffer[i]);//helloworld123 } } } catch (IOException e) { e.printStackTrace(); } finally { try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } }
-
-
写出操作:
FileWriter fileWriter = null; try { File file1 = new File("D:\\hh.txt"); fileWriter = new FileWriter(file1); //如果文件不存在:会自动创建该文件 //但如果目录不存在:并不会自动造目录 //如果文件不存在: //1.若FileWriter构造器的参数append为false则对文件进行覆盖 fileWriter.write("aaa\n"); fileWriter.write("123"); //2.若FileWriter构造器的参数append为true则对文件进行追加操作 /*FileWriter fileWriter1 = new FileWriter(file1,true); fileWriter1.write("456");*/ } catch (IOException e) { e.printStackTrace(); } finally { try { fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } }
-
使用FileReader与FileReader对文本文件实现复制操作
文本文件(.txt、.java、.c、.cpp)只能使用字符流操作,因为如果有中文的话,字节数组中放不下中文编码(使用字节流处理文本文件,仅限于复制文件的操作(不会在内存中转换显示))
FileReader fileReader = null; FileWriter fileWriter = null; try { File file1 = new File("D:\\hh.txt"); File file2 = new File("D:\\h2.txt"); fileReader = new FileReader(file1); fileWriter = new FileWriter(file2); char[] charsBuffer = new char[5]; int read; while ((read = fileReader.read(charsBuffer)) != -1){ fileWriter.write(charsBuffer,0,read); } } catch (IOException e) { e.printStackTrace(); } finally { try { if(fileReader != null) fileReader.close(); } catch (IOException e) { e.printStackTrace(); } try { if(fileWriter != null) fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } }
-
实现复制图片的操作:
图片是字节文件,(非文本文件,如视频图片)不能使用FileReader和FileWriter操作,要使用字节流fileInputStream和fileOutputStream,且charsBuffer数组要是字节类型的(byte [ ])
FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; try { File file1 = new File("D:\\123.png"); File file2 = new File("D:\\111.png"); fileInputStream = new FileInputStream(file1); fileOutputStream = new FileOutputStream(file2); byte[] charsBuffer = new byte[1024]; //缓存数组大小通常写为1024 int read; while ((read = fileInputStream.read(charsBuffer)) != -1){ fileOutputStream.write(charsBuffer,0,read); } } catch (IOException e) { e.printStackTrace(); } finally { try { if(fileInputStream != null) fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } try { if(fileOutputStream != null) fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } }
12.4 缓冲流(处理流1-提高速度)
-
缓冲流:提高流的读取、写入的速度
- BufferedInputStream
- BufferedOutputStream
- BufferedReader
- BufferedWriter
-
复制非文本文件示例:
BufferedInputStream bufferedInputStream = null; BufferedOutputStream bufferedOutputStream = null; try { File file1 = new File("D:\\123.png"); File file2 = new File("D:\\133.png"); FileInputStream fileInputStream = new FileInputStream(file1); FileOutputStream fileOutputStream = new FileOutputStream(file2); bufferedInputStream = new BufferedInputStream(fileInputStream); bufferedOutputStream = new BufferedOutputStream(fileOutputStream); byte[] bytes = new byte[1024]; int read; while ((read = bufferedInputStream.read(bytes)) != -1 ){ bufferedOutputStream.write(bytes,0,read); } } catch (IOException e) { e.printStackTrace(); } finally { //要求:先关外层,再关外层 try { bufferedInputStream.close(); } catch (IOException e) { e.printStackTrace(); } try { bufferedOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } //说明:外层流关闭时,内层流也会自动进行关闭,故可以省略关闭内层 //fileInputStream.close(); //fileOutputStream.close(); }
-
速度提高的原因:
-
内部提供了一个缓存区
-
public class BufferedInputStream extends FilterInputStream { private static int DEFAULT_BUFFER_SIZE = 8192; public BufferedInputStream(InputStream in) { this(in, DEFAULT_BUFFER_SIZE); }
-
-
处理流就套接在已有流的基础上的
bufferedInputStream = new BufferedInputStream(fileInputStream); bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
-
文本文件的复制操作示例:
BufferedReader br = null; BufferedWriter bw = null; try { File file1 = new File("D:\\h2.txt"); File file2 = new File("D:\\h3.txt"); FileReader fr= new FileReader(file1); FileWriter fw = new FileWriter(file2); br = new BufferedReader(fr); bw = new BufferedWriter(fw); /* //方式一: char[] bytes = new char[1024]; int read; while ((read = br.read()) != -1 ){ bw.write(bytes,0,read); }*/ //方式二:⭐一行一行读 String data; while ((data = br.readLine()) != null){ bw.write(data);//data中不好含换行符 bw.newLine();//换行 } } catch (IOException e) { e.printStackTrace(); } finally { //要求:先关外层,再关外层 try { br.close(); } catch (IOException e) { e.printStackTrace(); } try { bw.close(); } catch (IOException e) { e.printStackTrace(); } //说明:外层流关闭时,内层流也会自动进行关闭,故可以省略关闭内层 //fileInputStream.close(); //fileOutputStream.close(); }
-
例题:
-
实现图片的加密:(解密同理)
byte[] bytes = new byte[1024]; int read; while ((read = bufferedInputStream.read(bytes)) != -1 ){ for (int i = 0; i < read; i++) { bytes[i] = (byte) (bytes[i]^5); } bufferedOutputStream.write(bytes,0,read); }
-
统计文本上每个字符的个数:
FileReader fr = null; BufferedWriter bw = null; try { //1.创建Map集合 Map<Character, Integer> map = new HashMap<Character, Integer>(); //2.遍历每一个字符,每一个字符出现的次数放到map中 fr = new FileReader("D:\\h2.txt"); int c = 0; while ((c = fr.read()) != -1) { //int 还原 char char ch = (char) c; // 判断char是否在map中第一次出现 if (map.get(ch) == null) { map.put(ch, 1); } else { map.put(ch, map.get(ch) + 1); } } //3.把map中数据存在文件count.txt //3.1 创建Writer bw = new BufferedWriter(new FileWriter("D:\\word.txt")); //3.2 遍历map,再写入数据 Set<Map.Entry<Character, Integer>> entrySet = map.entrySet(); for (Map.Entry<Character, Integer> entry : entrySet) { switch (entry.getKey()) { case ' ': bw.write("空格=" + entry.getValue()); break; case '\t'://\t表示tab 键字符 bw.write("tab键=" + entry.getValue()); break; case '\r':// bw.write("回车=" + entry.getValue()); break; case '\n':// bw.write("换行=" + entry.getValue()); break; default: bw.write(entry.getKey() + "=" + entry.getValue()); break; } bw.newLine(); } } catch (IOException e) { e.printStackTrace(); } finally { //4.关流 if (fr != null) { try { fr.close(); } catch (IOException e) { e.printStackTrace(); } } if (bw != null) { try { bw.close(); } catch (IOException e) { e.printStackTrace(); } } }
-
12.5 转换流(处理流2-转换字符与字节)
-
转换流:
- FileInputStream:将一个字节输入流转换为字符输入流
- InputStreamReader:将一个字符输出流转换成字节输出流
-
作用:提供字节流与字符流之间的转换
-
在读入文件时,使用UTF-8字符集,在写出文件时,使用GBK字符集
File file1 = new File("D:\\h2.txt"); File file2 = new File("D:\\h4.txt"); FileInputStream fis = new FileInputStream(file1); FileOutputStream fos = new FileOutputStream(file2); //参数1:字节流;参数2:使用系统默认的字符集 InputStreamReader isr = new InputStreamReader(fis,"utf-8"); //参数2,指定字符集,具体使用哪个字符集,取决于文件保存时使用的字符集 //InputStreamReader isr = new InputStreamReader(fis,"UTF-8"); //输出时:使用gbk字符集将字节转化成字符 OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk"); char[] chars = new char[1024]; int len; while ((len = isr.read()) != -1){ osw.write(chars,0,len); } isr.close(); osw.close();
-
常见的编码表
-
ASCII: 美国标准信息交换码:用一个字节的7位可以表示
-
ISO8859-1:拉丁码表,欧洲码表用一个字节的8位表示
-
GB2312: 最初的中文编码表,最多两个字节编码所有字符
-
GBK: 中文编码表升级,融合了更多的中文文字符号。最多两个字节编码
-
Unicode: 国际标准码, 融合了目前人类使用的所有字符。为每个字符分配唯一的字符码,所有的文字都用两个字节来表示,是对UTF-8、UCS-2/UTF-16等具体编码方案的统称而已,并不是具体的编码方案
-
UTF-8: 变长的编码方式,可用1-4个字节来表示一个字符,UTF-8就是每次8个位传输数据,而UTF-16就是每次16个位
-
12.6 标准输入、输出流(处理流3)
-
System:
- PrintStream
System.er
:The “standard” error output stream - InputStream
System.in
:The “standard” input stream,标准输入流,默认从键盘输入 - PrintStream
System.out
:The “standard” output stream,标准输出流,默认从控制台输出
- PrintStream
-
System类的
setIn(InputStream is)
和setOut(PrintStream ps)
方式重新指定输入和输出的方式 -
练习题:
从键盘输入字符串,要求将读取到的整行字符串转成大写输出。然后继续进行输入操作,直至当输入“e”或者“exit”时,退出程序
BufferedReader br = null; try { InputStreamReader isr = new InputStreamReader(System.in); br = new BufferedReader(isr); while (true){ String data = br.readLine(); if(data.equalsIgnoreCase("e") || data.equalsIgnoreCase("eexit")){ System.out.println("程序结束"); break; } String toUpperCase = data.toUpperCase(Locale.ROOT); System.out.println(toUpperCase); } } catch (IOException e) { e.printStackTrace(); } finally { try { br.close(); } catch (IOException e) { e.printStackTrace(); } }
12.7 打印流
-
实现将基本数据类型的数据格式转化为字符串输出
-
打印流: PrintStream和PrintWriter
- 提供了一系列重载的
print()
和println()
方法,用于多种数据类型的输出 - PrintStream和PrintWriter的输出不会抛出IOException异常
- PrintStream和PrintWriter有自动flush功能
- PrintStream 打印的所有字符都使用平台的默认字符编码转换为字节。在需要写入字符而不是写入字节的情况下,应该使用 PrintWriter 类。
- System.out返回的是PrintStream的实例
- 提供了一系列重载的
-
示例:
PrintStream ps = null; try { FileOutputStream fos = new FileOutputStream(new File("D:\\text.txt")); // 创建打印输出流,设置为自动刷新模式(写入换行符或字节 '\n' 时都会刷新输出缓冲区) ps = new PrintStream(fos, true); if (ps != null) { System.setOut(ps);// 把标准输出流(控制台输出)改成文件 } for (int i = 0; i <= 255; i++) { // 输出ASCII字符 System.out.print((char) i); if (i % 50 == 0) { // 每50个数据一行 System.out.println(); // 换行 } } } catch (FileNotFoundException e) { e.printStackTrace(); } finally { if (ps != null) { ps.close(); } }
12.8 数据流
-
(用于读取和写出基本数据类型、 String类的数据
-
数据流有两个类:DataInputStream 和 DataOutputStream
-
分别“套接”在 InputStream 和 OutputStream 子类的流上
-
DataInputStream中的方法
boolean readBoolean()
char readChar()
double readDouble()
long readLong()
String readUTF()
byte readByte()
float readFloat()
short readShort()
int readInt()
void readFully(byte[] b)
-
DataOutputStream中的方法
将上述的方法的read改为相应的write即可
-
-
示例:
将文件中存储的基本数据类型或字符串读取到内存中,保存在变量中
或将内存中的变量的内容,持久化到文件当中
//写入 DataOutputStream dos = null; try { // 创建连接到指定文件的数据输出流对象 dos = new DataOutputStream(new FileOutputStream("destData.dat")); dos.writeUTF("我爱北京天安门"); // 写UTF字符串 dos.writeBoolean(false); // 写入布尔值 dos.writeLong(1234567890L); // 写入长整数 System.out.println("写文件成功!"); } catch (IOException e) { e.printStackTrace(); } finally { // 关闭流对象 try { if (dos != null) { // 关闭过滤流时,会自动关闭它包装的底层节点流 dos.close(); } } catch (IOException e) { e.printStackTrace(); } } //读出(读的顺序按写入的顺序来) DataInputStream dis = null; try { dis = new DataInputStream(new FileInputStream("destData.dat")); String info = dis.readUTF(); boolean flag = dis.readBoolean(); long time = dis.readLong(); System.out.println(info); System.out.println(flag); System.out.println(time); } catch (Exception e) { e.printStackTrace(); } finally { if (dis != null) { try { dis.close(); } catch (IOException e) { e.printStackTrace(); } } }
12.9 对象流
-
可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回
-
序列化:用
ObjectOutputStream
类(将内存中的Java对象保存到磁盘中,或通过网络传输出去)
反序列化: 用ObjectInputStream
类(将磁盘中的对象还原为内存中的Java对象) -
对象的序列化机制:
-
允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点
-
当其它程序获取了这种二进制流,就可以恢复成原来的Java对象
-
不能序列化static和transient(不想让某属性可序列化时使用)修饰的成员变量
-
对象所属的类一定是可序列化的
- 需要该类实现Serializable接口
- 需要该类提供一个常量serialVersionUID:若对象序列化后,所属类若类做了修改, 且没有定义serialVersionUID,则在反序列化中,对象就找不到自己的所属类了
- 该类内部的所有属性也是可序列化的(基本数据类型默认都是可序列化的)
public class Person implements Serializable { public static final long serialVersionUID = 4687687868L; private Accont accont;//Accont类也需要是可序列化的 }
-
-
序列化:
ObjectOutputStream oos = null; try { FileOutputStream fos = new FileOutputStream("D:\\h2.txt"); oos = new ObjectOutputStream(fos); oos.writeObject(new String("AAA")); oos.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { oos.close(); } catch (IOException e) { e.printStackTrace(); } }
-
反序列化:
ObjectInputStream ois = null; try { FileInputStream fis = new FileInputStream("D:\\h2.txt"); ois = new ObjectInputStream(fis); Object o = ois.readObject(); String str = (String) o; System.out.println(str);//AAA } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { try { ois.close(); } catch (IOException e) { e.printStackTrace(); } }
12.10 随机存取文件流
-
RandomAccessFile 声明在java.io包下,但直接继承于java.lang.Object类
-
实现了
DataInput
、DataOutput
这两个接口,也就意味着这个类既可以读也可以写 -
支持 “随机访问” 的方式,程序可以直接跳到文件的任意地方来读、写文件
- 支持只访问文件的部分内容
- 可以向已存在的文件后追加内容
-
复制示例:
RandomAccessFile raf1 = null; RandomAccessFile raf2 = null; try { raf1 = new RandomAccessFile(new File("D:\\h2.txt"),"r"); raf2 = new RandomAccessFile(new File("D:\\h5.txt"),"rw"); byte[] bytes = new byte[1024]; int len; while ((len = raf1.read(bytes)) != -1){ raf2.write(bytes,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { ... }
-
如果RandomAccessFile作为输出流时:
- 写出到的文件不存在,则在执行过程中自动创建
- 写出到的文件存在,则对源文件进行覆盖(默认从开始处覆盖)
RandomAccessFile raf = new RandomAccessFile(new File("D:\\h2.txt"), "rw"); raf.write("xyz".getBytes(StandardCharsets.UTF_8)); raf.close();
-
RandomAccessFile 对象包含一个记录指针,用以标示当前读写处的位置,可以自由移动记录指针:
void seek(long pos)
: 将文件记录指针定位到 pos 位置RandomAccessFile raf = new RandomAccessFile(new File("D:\\h2.txt"), "rw"); //1.将指针调到角标为1的位置,从1开始覆盖 //raf.seek(1); //2.实现末尾追加 //raf.seek(raf.length()); //3.实现中间插入的效果 //stringBuilder用于保存插入位置之后的内容 StringBuilder stringBuilder = new StringBuilder((int) new File("D:\\h2.txt").length()); //读出插入位置之后的内容 byte[] bytes = new byte[1024]; int len; while ((len = raf.read(bytes)) != -1){ stringBuilder.append(new String(bytes,0,len)); } //写入目标内容 raf.seek(3); raf.write("xyz".getBytes(StandardCharsets.UTF_8)); //写入stringBuilder中保存的内容 raf.write(stringBuilder.toString().getBytes(StandardCharsets.UTF_8)); raf.close();
12.11 NIO.2中Path、Paths、Files类的使用
-
Java NIO (New IO, Non-Blocking IO)是从Java 1.4版本开始引入的一套新的IO API,可以替代标准的Java IO API。 NIO与原来的IO有同样的作用和目的,但是使用的方式完全不同, NIO支持面向缓冲区的(IO是面向流的)、基于通道的IO操作。 NIO将以更加高效的方式进行文件的读写操作
-
JDK 7对NIO进行了极大的扩展,增强了对文件处理和文件系统特性的支持,以至于我们称他们为 NIO.2
-
Path、 Paths和Files核心API
-
早期只提供了一个File类来访问文件系统,但File类的功能比较有限,所提供的方法性能也不高。而且, 大多数方法在出错时仅返回失败,并不会提供异常信息
-
为了弥补这种不足,引入了Path接口,代表一个平台无关的平台路径,描述了目录结构中文件的位置。 Path可以看成是File类的升级版本,实际引用的资源也可以不存在
-
NIO.2在java.nio.file包下还提供了Files、 Paths工具类, Files包含了大量静态的工具方法来操作文件; Paths则包含了两个返回Path的静态工厂方法。
Paths 类提供的静态 get() 方法用来获取 Path 对象
-