【JavaSE】IO流

尚硅谷JavaSE笔记合集

文章名链接
【JavaSE】异常文章地址
【JavaSE】常用类:String、LocalDateTime…文章地址
【JavaSE】枚举文章地址
【JavaSE】注解文章地址
【JavaSE】集合框架文章地址 | HashMap源码解析 | List相关实现类源码解析
【JavaSE】泛型文章地址
【JavaSE】IO流文章地址 | 字符编码详解
【JavaSE】网络编程,BIO需求演进文章地址
【JavaSE】反射文章地址
【JavaSE】jdk8新特性文章地址

字符编码详解—点击进入

一、File类

1.1 实例化方法

  • java.io.File :文件文件目录 的抽象表示形式(与平台无关)
  • 程序中的File对象,可能没有一个真实存在的文件或目录
  • 访问文件内容,需要使用输入/输出流

注意:盘符 与 路径

/**
 *      1.如何创建file类的实例
 *          - File(String):通过 绝对路径或者相对路径 创建File对象
 *          - File(String,String):通过 路径(String+String) 创建File对象
 *          - File(File,String):通过 File对象+String路径 创建对象
 *      2.路径:
 *          - 相对路径:相对于 当前工程或者当前模块,取决于运行程序的对象
 *          - 绝对路径:包含盘符
 *
 *          - windows和DO系统分隔符:\\
 *          - unix和URL分隔符:/
 *          - 根据操作系统,File类动态提供的分隔符:public  static final String separator
 *        注意:Java程序支持跨平台运行,因此路径分隔符要慎用
 */
public class FileTest {
    @Test
    public void test1(){
        //1.String创建:文件不存在可以输出
        File file1=new File("hello.txt");
        File file2=new File("E:"+File.separator+"io");
        System.out.println(file1);
        System.out.println(file2);
        //2.String+String创建
        File file3=new File("E:\\","io");
        System.out.println(file3);
        //3.File+String创建
        File file4=new File(file3,"hello.txt");
        System.out.println(file4);
    }
}

1.2 创建、删除、重命名方法

/**
 *  创建硬盘中对应的文件或文件目录
 *     1.createNewFile() :创建文件。若文件存在,则失败返回false
 *     2.mkdir() :创建目录。若目录存在或上级目录不存在,则失败返回false
 *     3.mkdirs() :创建多级目录。若目录存在,失败返回false
 *   !!!注意:Java中的删除不走回收站。删除目录不能有子目录或文件
 *     4.delete():删除磁盘中的文件或者文件夹。
 *   !!!注意:如下方法调用者必须存在,参数必须不存在
 *     5.renameTo(File):重命名并移动
 */
public class FileCreateTest {
    @Test
    public void test1() throws IOException {
        File file =new File("hi.txt");
        if(file.exists()){
            //4.删除文件
            file.delete();
            System.out.println("删除文件成功!");
        }else {
            //1.创建文件
            file.createNewFile();
            System.out.println("创建文件成功!");
        }
        File dir1=new File("E:\\io");
        File dir2=new File("E:\\io\\io\\io");
        //2.创建目录
        boolean mkdir = dir1.mkdir();
        if (mkdir){
            System.out.println("目录创建成功");
        }
        //3.创建多级目录
        boolean mkdirs = dir2.mkdirs();
        if (mkdirs){
            System.out.println("创建多级目录成功!");
        }
    }
    @Test
    public void test3(){
        //5. 重命名并移动
        File file1=new File("hi.txt"); //!!!必须存在
        File file2=new File("hello.txt"); //!!!必须不存在
        file1.renameTo(file2);
    }
}

1.3 获取信息方法

  • list()、listFiles():可传入过滤器
/**
 *   - 1.getAbsolutePath():获取绝对路径
 *   - 2.getPath() :获取路径
 *   - 3.getName() :获取名称
 *   - 4.getParent():获取上层文件目录路径。若无,返回null
 *   - 5.length() :获取文件长度(即:字节数)。不能获取目录的长度。
 *   - 6.lastModified() :获取最后一次的修改时间,毫秒值
 * !!!注意:只适用于文件目录
 *   - 7.public String[] list() :获取指定目录下的所有文件或者文件目录的名称数组
 *   - 8.public File[] listFiles() :获取指定目录下的所有文件或者文件目录的File数组
 *	 - 扩展,方法中可传入过滤器
 */
public class FileTest {
    @Test
    public void test2(){
        File file1=new File("hello.txt");
        File file2=new File("E:\\hi.txt");
        //1. 获取绝对路径
        //F:\IDEA\JavaProjects\JavaseTest\IO_Demo\hello.txt
        //E:\hi.txt
        System.out.println(file1.getAbsolutePath()); 
        System.out.println(file2.getAbsolutePath()); 
        //2. 获取路径
        System.out.println(file1.getPath()); //hello.txt
        System.out.println(file2.getPath()); //E:\hi.txt
        //3. 获取名称
        System.out.println(file1.getName()); //hello.txt
        System.out.println(file2.getName()); //hi.txt
        //4. 获取上层文件目录路径。若无,返回null
        System.out.println(file1.getParent()); //null
        System.out.println(file2.getParent()); //E:\
        //5. 获取文件长度(即:字节数)。不能获取目录的长度。
        System.out.println(file1.length()); //0
        System.out.println(file2.length()); //0
        //6. 获取最后一次的修改时间,毫秒值
        System.out.println(file1.lastModified()); //0
        System.out.println(file2.lastModified()); //1665047928806
    }

    @Test
    public void test4(){
        //如下的两个方法适用于文件目录:
        File file3=new File("E:\\io");
        //7. 获取目录下所有 文件或目录名称 的String数组
        String[] list = file3.list();
        System.out.println(Arrays.toString(list)); //[dir, hi.txt]
        //8. 获取目录下所有 文件或目录 的File数组
        File[] files = file3.listFiles();
        System.out.println(Arrays.toString(files));//[E:\io\dir, E:\io\hi.txt]
    }
}

1.4 判断方法

/**
 *   1.isDirectory():判断是否是文件目录!!!常用
 *   2.isFile() :判断是否是文件!!!常用
 *   3.exists() :判断是否存在!!!常用
 *   4.canRead() :判断是否可读
 *   5.canWrite() :判断是否可写
 *   6.isHidden() :判断是否隐藏
 */
public class FileTest {
    @Test
    public void test5(){
        File file1=new File("hello.txt");
        File file2=new File("hello1.txt");
        File dir1=new File("E:\\io");
        File dir2=new File("E:\\io1");
        //1.判断是否是文件目录!!!常用
        System.out.println(file1.isDirectory()); //false
        System.out.println(file2.isDirectory()); //false
        System.out.println(dir1.isDirectory()); //true
        System.out.println(dir2.isDirectory()); //false
        //2.判断是否是文件!!!常用
        System.out.println(file1.isFile()); //true
        System.out.println(file2.isFile()); //false
        System.out.println(dir1.isFile()); //false
        System.out.println(dir2.isFile()); //false
        //3.判断是否存在!!!常用
        System.out.println(file1.exists()); //true
        System.out.println(file2.exists()); //false
        System.out.println(dir1.exists()); //true
        System.out.println(dir2.exists()); //false
        //4.判断是否可读
        System.out.println(file1.canRead()); //true
        System.out.println(file2.canRead()); //false
        System.out.println(dir1.canRead()); //true
        System.out.println(dir2.canRead()); //false
        //5.判断是否可写
        System.out.println(file1.canWrite()); //true
        System.out.println(file2.canWrite()); //false
        System.out.println(dir1.canWrite()); //true
        System.out.println(dir2.canWrite()); //false
        //6.判断是否隐藏
        System.out.println(file1.isHidden()); //false
        System.out.println(file2.isHidden()); //false
        System.out.println(dir1.isHidden()); //false
        System.out.println(dir2.isHidden()); //false
    }
}

1.5 练习

题目一

  • 在file目录下,创建多个文件和目录

  • 实现一个方法,用于删除file目录中指定的文件

public class Pratise1 {
    /**
     * 1.在file目录下,创建多个文件和目录。
     * 2.实现一个方法,用于删除file目录中指定的文件。
     */
    @Test
    public void test1() throws IOException {
        //1.在file目录下,创建多个文件和目录。
        File file=new File("E:\\pratise1");
        File file_hello=new File(file,"hello.txt");
        File file_hi=new File(file,"hi.txt");
        File dir_hello=new File(file,"hello");
        //不存在则创建成功,存在返回false
        file_hello.createNewFile();
        file_hi.createNewFile();
        dir_hello.mkdir();
        //2.实现一个方法,用于删除file目录中指定的文件
        //如果是目录,且不是空目录,则删除失败
        deleteFile(file,"hello.txt");
    }
    public boolean deleteFile(File dir,String filename){
        if (!dir.isDirectory()){
            System.out.println("删除失败,指定的文件不是目录!");
            return false;
        }
        File file=new File(dir,filename);
        if(file.delete()){
            System.out.println("删除成功!");
            return true;
        }else{
            System.out.println("删除失败!");
            return false;
        }
    }
}

题目二

  • 判断目录下是否有后缀名为.jpg的文件,有则输出文件名称
/**
 * 1.判断目录下是否有后缀名为.jpg的文件,有则输出文件名称
 */
public class Pratise2 {
    @Test
    //list()
    public void test1(){
        File file=new File("C:\\Users\\李泽伟\\Pictures\\Saved Pictures") ;
        String[] list = file.list();
        for (String s : list) {
            if (s.endsWith(".jpg")){
                System.out.println(s);
            }
        }
    }
    @Test
    //listFiles()
    public void test2(){
        File file=new File("C:\\Users\\李泽伟\\Pictures\\Saved Pictures") ;
        File[] files = file.listFiles();
        for (File file1 : files) {
            if (file1.getName().endsWith(".jpg")) System.out.println(file1.getName());
        }
    }
    @Test
    //listFiles()+FilenameFilter
    public void test3(){
        File file=new File("C:\\Users\\李泽伟\\Pictures\\Saved Pictures") ;
        File[] files = file.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.endsWith(".jpg");
            }
        });
        for (File file1 : files) {
            System.out.println(file1.getName());
        }
    }
}

题目三

  • 遍历目录,包括子目录和文件。输出目录结构

    • 计算目录占用的空间大小
    public class Pratise3 {
        @Test
        public void test1(){
            System.out.println("目录总大小为:"+eachDir1(new File("E:\\pratise3"), 0));
        }
        //1.计算目录占用的空间大小
        public Long eachDir1(File file,int num){
            //1.目录大小:用于遍历目录时对下属文件大小进行叠加
            Long size=0L;
            //2.获取层级
            int now=num;
            for (int i = 0; i < now; i++) {
                //3.输出对应的层级符
                System.out.print("--");
            }
            //4.输出当前file名
            System.out.println(file.getName());
            //5.如果是目录,则修改层级并对目录下的文件或目录进行递归
            if (file.isDirectory()){
                now++;
                File[] files = file.listFiles();
                //5.1.循环目录下属文件,叠加下属文件大小
                for (File file1 : files) {
                    size+=eachDir1(file1,now);
                }
                //5.2 返回目录大小
                return size;
            }else{
                //5.2 返回文件大小
                return file.length();
            }
        }
    }
    =============================================================================
    pratise3
    --1.txt
    --2.txt
    --3.txt
    --目录一
    ----4.txt
    ----目录二
    ------5.txt
    目录总大小为:85
    
  • 遍历目录,包括子目录和文件。输出目录结构

    • 删除目录下的所有子目录和文件
    public class Pratise3 {
        @Test
        public void test2(){
            eachDir2(new File("E:\\pratise4"), 0);
        }
        //2.删除目录下的所有子目录和文件
        public void eachDir2(File file,int num){
            //1.获取层级
            int now=num;
            for (int i = 0; i < now; i++) {
                //2.输出对应的层级符
                System.out.print("--");
            }
            //3.输出当前file名
            System.out.println(file.getName());
            //4.如果是目录,则修改层级并对目录下的文件或目录进行递归
            if (file.isDirectory()){
                now++;
                File[] files = file.listFiles();
                for (File file1 : files) {
                    eachDir2(file1,now);
                }
            }
            //5.输出层级关系进行删除操作:如果是第一层则目录则保留
            if (num!=0){
                file.delete();
            }
        }
    }
    

二、原理、分类

2.1 IO流原理

  • java.io
  • 输入input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。
  • 输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中。

2.2 流的分类

  • 操作数据的单位不同:字节流,字符流
  • 数据的流向不同:输入流,输出流
  • 流的角色的不同:节点流,处理流
抽象基类字节流字符流
输入流InputStreamReader
输出流OutputStreamWriter

在这里插入图片描述

2.3 IO 流体系

在这里插入图片描述

三、文件流/节点流

3.1 概述

/**
 * 注意:字符流和字节流不能乱用
 *   1. 对于文本文件(.txt,.java,.c,.cpp),使用字符流处理。
 *		  - 因为字符流处理时会使用字符集进行解码和编码,非文本文件的二进制数据存在字符编码表找不到的情况
 *		  		字符流:二进制数据 --编码-> 字符编码表 --解码-> 二进制数据
 *   2. 对于非文本文件(.jpg,.mp3,.mp4,.avi,.doc,.ppt,...),使用字节流处理。
 *		  - 	字节流:二进制数据 —> 二进制数据
 *
 * - 流的体系结构
 *  抽象基类         节点流(或文件流)
 *  InputStream     FileInputStream	  :read()、read(byte[])、read(byte[],int,int)
 *  OutputStream    FileOutputStream  :write(int)、write(byte[])、write(byte[],0,len)、FileOutputStream(file,true)追加文件
 *  Reader          FileReader        :read()、read(char[])、read(char[],int,int)
 *  Writer          FileWriter        :write(int)、write(char[])、write(char[],0,len)、FileWriter(file,true)追加文件
 * 
 */

3.2 FileReader-读入

/**
 *  读入:被读文件一定要存在,否则就会报FileNotFoundException
 *      - read():返回读入的一个字符。如果达到文件末尾,返回-1。
 *      - read(char[]):返回每次读入byte数组的字符个数。如果达到文件末尾,返回-1
 *   		注意:read(char[])是覆盖之前的数据
 *		- read(String)
 *		- read(char[],int,int)
 */
public class FileReadTest {
    //相较于当前工程
    public static void main(String[] args) {
        File file =new File("hello.txt");
        //F:\software\IDEA\JavaProjects\JavaseTest\hello.txt
        System.out.println(file.getAbsoluteFile()); 
    }
    @Test
    //相较于当前的Module:read()
    public void test1(){
        FileReader fr= null;
        try {
            //1.实例化要操作文件的File对象
            File file =new File("hello.txt");
            //2.创建与之连接的流
            fr = new FileReader(file);
            int data;
            //3.读取数据
            while((data=fr.read())!=-1){
                System.out.println((char)data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭流
            if (fr!=null){
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    @Test
    //相较于当前的Module:read(char[])
    public void test2(){
        FileReader fr= null;
        try {
            //1.实例化要操作文件的File对象
            File file =new File("hello.txt");
            //2.创建与之连接的流
            fr = new FileReader(file);
            int data;
            //3.读取数据
            int len;
            char[] buf=new char[5];
            while((len=fr.read(buf))!=-1){
                //方式一:
                //错误写法:i < buf.length
                for (int i = 0; i < len; i++) {
                    System.out.println(buf[i]);
                }
                //方式二
                //错误写法:new String(buf,0,buf.length)
                String str=new String(buf,0,len);
                System.out.println(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭流
            if (fr!=null){
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

3.3 FileWriter-写出

/**
 *  写出:写入的文件可以不存在的。并不会报异常
 *     - 文件不存在:自动创建
 *     - 文件存在:流在构造器中设置是否追加
 *          1.FileWriter(file,false) / FileWriter(file):覆盖
 *          2.FileWriter(file,true):追加
 *     - write(int)
 *     - write(String)
 *     - write(char[])
 *     - write(String,int,int)
 *     - write(char[],int,int)
 */
public class FileWriteTest {
    //write(String)
    @Test
    public void test1(){
        FileWriter fw= null;
        try {
            //1.实例化要操作文件的File对象
            File file=new File("hello.txt");
            //2.创建与之连接的流
            fw = new FileWriter(file,true);
            //3.写入数据
            fw.write("1");
            fw.write("2");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fw!=null){
                try {
                    //4.关闭流
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

3.4 文本复制

注意:不能使用字符流来处理图片等字节数据

/**
 * 文件字符流输入输出实现文本复制
 * 注意:不能使用字符流来处理图片等字节数据
 */
public class ReadWriteCopyTest {
    //read(char[])、write(char[],int,int)
    @Test
    public void test1(){
        FileReader fr= null;
        FileWriter fw= null;
        try {
            //1.实例化要操作文件的File对象
            File src=new File("hello.txt");
            File dest=new File("copy.txt");
            //2.创建与之连接的流
            fr = new FileReader(src);
            fw = new FileWriter(dest);
            char[] buf=new char[5];
            int length;
            //3.读写数据
            while((length=fr.read(buf))!=-1){
                fw.write(buf,0,length);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭流
            if (fr!=null){
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fw!=null){
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

3.5 FileInputStream-读文本乱码

/**
 *	读:
 *		- read()
 *		- read(byte[])
 *		- read(byte[],int,int)
 *	写:
 *		- write(int)
 *		- write(byte[])
 *		- write(byte[],int,int)
 *
 * 注意:不能使用字符流来处理图片等字节数据
 */
public class FileInputTest {
    //read(byte[])、new String(byte[],int,int)
    @Test
    public void test1(){
        FileInputStream fis= null;
        try {
            //1.实例化要操作文件的File对象
            File file=new File("hello.txt"); //hello中
            //2.创建与之连接的流
            fis = new FileInputStream(file);
            byte[] buf=new byte[3];
            int length;
            //3.读取数据
            while((length=fis.read(buf))!=-1){
                //由于“中”在文本中编码为三个字节,在读取时被拆开,所以解码字符错误
                System.out.println(new String(buf,0,length)); //hel lo� ��
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭流
            if (fis!=null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

3.6 非文本复制

/**
 *  实现:文件字节流输入输出实现图片复制
 *
 *	读:
 *		- read()
 *		- read(byte[])
 *		- read(byte[],int,int)
 *	写:
 *		- write(int)
 *		- write(byte[])
 *		- write(byte[],int,int)
 *
 */
public class InputOutputCopy {
    //read(byte[])、write(byte[],int,int)
    @Test
    public void test(){
        File src=new File("C:\\Users\\李泽伟\\Pictures\\Saved Pictures\\QQ图片20200223235928.jpg");
        File dest=new File("1.jpg");
        Long start=System.currentTimeMillis();
        testCopyFile(src,dest);
        Long end=System.currentTimeMillis();
        System.out.println("花费时间:"+(end-start)); //288
    }
    public void testCopyFile(File src, File dest){
        FileInputStream fis= null;
        FileOutputStream fos= null;
        try {
            fis = new FileInputStream(src);
            fos = new FileOutputStream(dest);
            byte[] buf=new byte[1024];
            int length;
            while((length=fis.read(buf))!=-1){
                fos.write(buf,0,length);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis!=null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos!=null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

四、缓冲流

4.1 概述

  • 提高输入、输出效率
  • 缺省创建一个8192个字节(8Kb)的内部缓冲区数组
    • 先把数据 读/写 到缓冲区中,装满后再一次性 读/写 到输入输出流
  • 需要“套接”在节点流之上
/**
 *	注意:
 *		- 需要“套接”在节点流之上
 *		- 关闭最外层流即可,内层节点流会自动关闭。自动刷新缓存区
 *
 * 抽象基类                   缓冲流(处理流的一种)
 * InputStream            	BufferedInputStream		:
 * OutputStream      		BufferedOutputStream	:flush()
 * Reader                   BufferedReader			:readLine()
 * Writer                   BufferedWriter			:newLine()、flush()
 *
 */

4.2 非文本复制

/**
 *  缓冲流:非文本文件复制
 *		- flush()
 *      - 只需关闭外层流,自动刷新缓冲区
 */
public class InputOutputCopy {
    @Test
    public void test(){
        BufferedInputStream bis= null;
        BufferedOutputStream bos= null;
        try {
            //1.创建文件对象
            File src=new File("1.jpg");
            File dest=new File("2.jpg");
            //2.创建文件的连接流
            FileInputStream fis=new FileInputStream(src);
            FileOutputStream fos=new FileOutputStream(dest);
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);
            //3.数据读写实现复制
            byte[] buf=new byte[1024];
            int length;
            while((length=bis.read(buf))!=-1){
                bos.write(buf,0,length);
                //bos.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.资源关闭
            if(bis!=null){
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bos!=null){
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

4.2 证明缓冲流效果

/**
 *  证明:缓冲流提高输入、输出效率
 *		没有缓冲:288。具体实现参考3.6节
 *		加上缓冲:4
 */
public class EffectTest {
    @Test
    public void test(){
        File src=new File("C:\\Users\\李泽伟\\Pictures\\Saved Pictures\\QQ图片20200223235928.jpg");
        File dest=new File("1.jpg");
        Long start=System.currentTimeMillis();
        testCopyFileBuf(src,dest);
        Long end=System.currentTimeMillis();
        System.out.println("花费时间:"+(end-start)); //288 -> 4
    }
    public void testCopyFileBuf(File src, File dest){
        BufferedInputStream bis= null;
        BufferedOutputStream bos= null;
        try {
            //1.实现流与文件的连接
            bis = new BufferedInputStream(new FileInputStream(src));
            bos = new BufferedOutputStream(new FileOutputStream(dest));
            //2.输入输出操作
            byte[] buf = new byte[1024];
            int length;
            while ((length = bis.read(buf)) != -1) {
                bos.write(buf, 0, length);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //3.关闭资源
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在这里插入图片描述

4.3 文本复制

/**
 *  文本复制
 *      - String readLine()
 *      - newLine()/ +"\n"
 */
public class ReadWriteTest {
    @Test
    public void test(){
        BufferedReader br= null;
        BufferedWriter bw= null;
        try {
            //1.实现流与文件的连接
            br = new BufferedReader(new FileReader("copy.txt"));
            bw = new BufferedWriter(new FileWriter("copy1.txt"));
            //2.实现输入输出
            //方式一
//        char[] flush=new char[1024];
//        int length;
//        while((length=br.read(flush))!=-1){
//            bw.write(flush);
//        }
            //方式二
            String data;
            while((data=br.readLine())!=null){
//                bw.write(data+"\n");
                bw.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //3.关闭资源
            if (br!=null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bw!=null){
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在这里插入图片描述

4.4 课后练习

练习1:证明缓存流的作用

参考4.2小节

练习2

实现照片的加密

/**
 * 练习2:实现照片的加密与解密
 */
public class Encode {
    @Test
    public void test1(){
        BufferedInputStream bis= null;
        BufferedOutputStream bos= null;
        try {
            //1.实现流与文件的连接
            bis = new BufferedInputStream(new FileInputStream("1.jpg"));
            bos = new BufferedOutputStream(new FileOutputStream("3.jpg"));
            //2.实现图片复制+加密
            byte[] buf=new byte[1024];
            int length;
            while((length=bis.read(buf))!=-1){
                for (int i = 0; i < length; i++) {
                    buf[i]= (byte) (buf[i] ^ 5);
                }
                bos.write(buf);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //3.资源关闭
            if (bis!=null){
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bos!=null){
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
    @Test
    public void test2(){
        BufferedInputStream bis= null;
        BufferedOutputStream bos= null;
        try {
            //1.实现流与文件的连接
            bis = new BufferedInputStream(new FileInputStream("3.jpg"));
            bos = new BufferedOutputStream(new FileOutputStream("4.jpg"));
            //2.实现图片复制+解密
            byte[] buf=new byte[1024];
            int length;
            while((length=bis.read(buf))!=-1){
                for (int i = 0; i < length; i++) {
                    buf[i]= (byte) (buf[i] ^ 5);
                }
                bos.write(buf);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //3.资源关闭
            if (bis!=null){
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bos!=null){
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

练习3

统计文本文件上每个字符出现的次数

/**
 *  练习3:统计文本文件上每个字符出现的次数
 */
public class CharCount {
    @Test
    public void test(){
        BufferedReader br= null;
        BufferedWriter bw= null;
        try {
            //1.实现文件与流的连接
            br = new BufferedReader(new FileReader("hello.txt"));
            bw = new BufferedWriter(new FileWriter("charCount.txt"));
            //2.统计
            char[] flush=new char[1024];
            int length;
            //定义map集合
            Map<Character,Integer> map=new HashMap<Character,Integer>();
            //遍历char型数组,判断元素是否为map中的key
            //是则添加:key-value+1
            //否则添加:key-1
            while((length=br.read(flush))!=-1){
                for (int i = 0; i < length; i++) {
                    if (map.get(flush[i])!=null) {
                        map.put(flush[i],map.get(flush[i])+1);
                    }else{
                        map.put(flush[i],1);
                    }
                }
            }
            //3.输出统计结果
            Set<Map.Entry<Character, Integer>> entries = map.entrySet();
            for (Map.Entry<Character,Integer> entry : entries) {
                switch (entry.getKey()){
                    case ' ':
                        bw.write("空格="+entry.getValue());
                        break;
                    case '\t':
                        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(br!=null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(bw!=null){
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

五、转换流

5.1 概述

  • 提供字节流与字符流之间的转换
  • 字节流中的数据都是字符时,转成字符流操作更高效。
  • 很多时候我们使用转换流来处理文件乱码问题。实现编码和解码的功能。
/**
 *	- 属于字符流
 *      InputStreamReader:字节输入流 --> 字符的输入流
 *      OutputStreamWriter:字符输出流 --> 字节的输出流
 *
 *
 * 	  抽象基类              转换流(处理流的一种)
 * 	InputStream
 * 	OutputStream
 * 	Reader               InputStreamReader		:InputSreamReader(InputStream,String)编码方式
 * 	Writer               OutputStreamWriter		:OutputSreamWriter(OutputStream,String)编码方式
 *
 */

在这里插入图片描述

5.2 改变编码格式

/**
 *  转换流:实现文本文件编码格式的转换
 *  	- 解码:字节、字节数组   --->  字符数组、字符串
 *  	- 编码:字符数组、字符串 --->  字节、字节数组
 */
public class InputStreamReaderTest {
    @Test
    public void test(){
        InputStreamReader isr= null;
        OutputStreamWriter osw= null;
        try {
            //1.实现文件与流的连接
            //参数2指明了字符集,具体使用哪个字符集,取决于文件hello.txt保存时使用的字符集
            isr = new InputStreamReader(new FileInputStream("hello.txt"),"utf-8");
            osw = new OutputStreamWriter(new FileOutputStream("hello_gbk.txt"),"gbk");
            //2.数据格式改变
            char[] flu=new char[20];
            int length;
            while((length=isr.read(flu))!=-1){
                osw.write(flu,0,length);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //3.关闭资源
            if (isr!=null){
                try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (osw!=null){
                try {
                    osw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

六、标准输入、输出流

  • System.in
    • 系统标准的输入设备,默认为键盘
    • 类型是InputStream
  • System.out
    • 分系统标准的输出设备,默认为显示器
    • 类型是PrintStream,其是FilterOutputStream的子类 --> OutputStream的子类
  • 重定向:改变系统默认设备
    • System.setIn(InputStreamin)
    • System.setOut(PrintStreamout)
/**
 *
 *  练习:从键盘输入字符串,要求将读取到的整行字符串转成大写输出。然后继续进行输入操作,
 *        -  直至当输入“e”或者“exit”时,退出程序。
 */
public class SystemInTest {
    public static void main(String[] args) {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(System.in));
            while(true){
                System.out.println("请输出字符串:");
                String data=br.readLine();
                if ("e".equalsIgnoreCase(data) || "exit".equalsIgnoreCase(data)) {
                    System.out.println("退出程序!");
                    break;
                }
                System.out.println(data.toUpperCase());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br!=null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
/**
 *  练习:模拟Scanner,将每行输入转换为int、double、float、boolean、short、byte、String
 */
public class ScannerTest {
    private static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

    public static String nextStr(){
        String data=null;
        try {
            data=br.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return data;
    }
    public int nextInt() {
        return Integer.parseInt(nextStr());
    }
    public double nextDouble() {
        return Double.parseDouble(nextStr());
    }
    public double nextFloat() {
        return Float.parseFloat(nextStr());
    }
    public boolean nextBoolean() {
        return Boolean.parseBoolean(nextStr());
    }
    public double nextShort() {
        return Short.parseShort(nextStr());
    }
    public double nextByte() {
        return Byte.parseByte(nextStr());
    }
}

七、打印流

  • 实现将基本数据类型的数据格式转化为字符串输出
  • 打印流:PrintStream和PrintWriter
    • 一系列的 print(重载)、println(重载) ,用于多种数据类型的输出
    • 不会抛出IOException异常
    • 有自动flush功能
/**
 *
 *  打印流练习:将系统标准输出流进行重定向
 *
 * 	  抽象基类              打印流(处理流的一种)
 * 	InputStream
 * 	OutputStream		 PrintStream:	print()、println()、PrintStream(OutputStream,boolean)是否自动刷新缓存
 * 	Reader               
 * 	Writer               PrintWriter:	print()、println()、PrintWriter(OutputStream,boolean)是否自动刷新缓存
 *
 */
public class PrintStreamTest {
    @Test
    public void test(){
        PrintStream ps= null;
        try {
            ps = new PrintStream(new FileOutputStream("printStream.txt"),true);
            //重定向系统输出
            if (ps!=null) System.setOut(ps);
            // 输出ASCII字符
            for (int i = 0; i <= 255; i++) {
                // 每50个数据一行
                if (i%50==0){
                    System.out.println();
                }
                System.out.print((char)(i-1));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (ps!=null){
                ps.close();
            }
        }
    }
}

八、数据流

  • 操作 基本数据类型、String 数据
  • 注意:读取不同类型的数据的顺序要与当初写入文件时,保存的数据的顺序一致!
/**
 * 
 *   练习1:将内存中的字符串、基本数据类型的变量写出到文件中。
 *	 练习2:将文件中的字符串、基本数据类型的变量读取到内存中。
 *
 * 	  抽象基类              打印流(处理流的一种)
 * 	InputStream			 DataInputStream:	readUTF()、readFully(byte[])、readBoolean()、readByte()、readChar()...
 * 	OutputStream		 DataOutputStream:	writeUTF()、writeFully(byte[])、writeBoolean()、writeByte()、writeChar()...
 * 	Reader               
 * 	Writer               
 *
 */
public class OtherStreamTest {    
	//练习1:将内存中的字符串、基本数据类型的变量写出到文件中。
    @Test
    public void test3() throws IOException {
        //1.
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
        //2.
        dos.writeUTF("刘刚");
        dos.flush();//刷新操作,将内存中的数据写入文件
        dos.writeInt(23);
        dos.flush();
        dos.writeBoolean(true);
        dos.flush();
        //3.
        dos.close();
    }

	//练习2:将文件中的字符串、基本数据类型的变量读取到内存中。
    @Test
    public void test4() throws IOException {
        //1.
        DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
        //2.
        String name = dis.readUTF();
        int age = dis.readInt();
        boolean isMale = dis.readBoolean();
        System.out.println("name = " + name);
        System.out.println("age = " + age);
        System.out.println("isMale = " + isMale);
        //3.
        dis.close();

    }
}

九、对象流

9.1 序列化机制

  • 序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象
  • 序列化是RMI(Remote Method Invoke –远程方法调用)过程的参数和返回值都必须实现的机制,而RMI 是JavaEE的基础。因此序列化机制是JavaEE平台的基础
  • 对象支持序列化机制的要求
    • 类实现了 Serializable接口Externalizable接口
    • 类提供一个全局常量:serialVersionUID
    • 保证其内部所有属性也必须是可序列化的
    • statictransient修饰的成员变量不能序列化

9.2 序列化与反序列化

/**
 *	作用:存储和读取基本数据类型数据或对象的处理流。强大之处在于:
 *		1.序列化:可以把内存中的java对象写入到数据源或通过网络传输出去
 *		2.反序列化:可以把对象从数据源、网络中还原回来
 *
 * 	  抽象基类              对象流
 * 	InputStream			 ObjectInputStream(反序列化):		readObject()	
 * 	OutputStream		 ObjectOutputStream(序列化):		writeObject()、flush()
 * 	Reader               
 * 	Writer 
 */
public class ObjectIOTest {
    //1.序列化:可以把内存中的java对象写入到数据源或通过网络传输出去
    @Test
    public void test1(){
        ObjectOutputStream oos= null;
        try {
            //1.文件与流的连接
            oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
            //2.操作
            oos.writeObject(new String("我爱Java!"));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //3.关闭资源
            if (oos!=null){
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    //2.反序列化:可以把对象从数据源、网络中还原回来
    @Test
    public void test2(){
        ObjectInputStream ois= null;
        try {
            //1.文件与流的连接
            ois = new ObjectInputStream(new FileInputStream("object.dat"));
            //2.操作
            String str = (String) ois.readObject();
            System.out.println(str);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            //3.关闭资源
            if (ois!=null){
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

9.3 自定义可序列化类

  • 对象支持序列化机制的要求:
  • 类实现了 Serializable接口Externalizable接口
    • 类提供一个全局常量:serialVersionUID
    • 保证其内部所有属性也必须是可序列化的

注意statictransient 修饰的成员变量不能序列化

Person类

/**
 * 自定义可序列化类
 * 		1.实现接口:Serializable 或 Externalizable
 *		2.提供一个全局常量:serialVersionUID
 *		3.内部所有属性也必须是可序列化的。(默认情况下,基本数据类型、String等可序列化)
 *
 *   注意:ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量
 */
//1.实现接口:Serializable 或 Externalizable
public class Person implements Serializable {
    //2.提供一个全局常量:serialVersionUID
    private static final long serialVersionUID = -684966670754667710L;
    String name;
    int age;
    //3.保证内部所有属性是可序列化的
    Account account;
    //注意:static和transient修饰的成员变量不能序列化
    transient Long idCard;
    static String address="北京";

    public Person() {
    }
    public Person(String name, int age, Account account, Long idCard) {
        this.name = name;
        this.age = age;
        this.account = account;
        this.idCard = idCard;
    }
    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 Account getAccount() {
        return account;
    }
    public void setAccount(Account account) {
        this.account = account;
    }
    public Long getIdCard() {
        return idCard;
    }
    public void setIdCard(Long idCard) {
        this.idCard = idCard;
    }
    public static String getAddress() {
        return address;
    }
    public static void setAddress(String address) {
        Person.address = address;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", account=" + account +
                ", idCard=" + idCard +
                '}';
    }
}
//1.实现接口:Serializable 或 Externalizable
class Account implements Serializable {
    //2.提供一个全局常量:serialVersionUID
    private static final long serialVersionUID = -618956670754667710L;
    //3.保证内部所有属性是可序列化的
    Long balance;

    public Account() {
    }
    public Account(Long balance) {
        this.balance = balance;
    }
    public Long getBalance() {
        return balance;
    }
    public void setBalance(Long balance) {
        this.balance = balance;
    }
    @Override
    public String toString() {
        return "Account{" +
                "balance=" + balance +
                '}';
    }
}

测试类

/**
 * 	ObjectInputStream(反序列化):		readObject()
 * 	ObjectOutputStream(序列化):		writeObject()、flush()
 */
public class DiySerializableObjectTest {
    //1.序列化:可以把内存中的java对象写入到数据源或通过网络传输出去
    @Test
    public void test1(){
        ObjectOutputStream oos= null;
        try {
            //1.文件与流的连接
            oos = new ObjectOutputStream(new FileOutputStream("person.dat"));
            //2.操作
            oos.writeObject(new Person("宋红康",30,new Account(10000000l),6745463544l));
            oos.flush();
            oos.writeObject(new Person("周阳",40,new Account(10000000l),5465454646l));
            oos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //3.关闭资源
            if (oos!=null){
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    //2.反序列化:可以把对象从数据源、网络中还原回来
    @Test
    public void test2(){
        ObjectInputStream ois= null;
        try {
            //1.文件与流的连接
            ois = new ObjectInputStream(new FileInputStream("person.dat"));
            //2.操作
            Person shk = (Person) ois.readObject();
            System.out.println(shk);
            Person zy = (Person) ois.readObject();
            System.out.println(zy);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            //3.关闭资源
            if (ois!=null){
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

9.4 serialVersionUID的理解

反例情况:
	1.创建Person类。不指定serialVersionUID,系统随机生成uid:111
	2.序列化Person对象A
	3.修改Person类。serialVersionUID修改为:222
	4.反序列化Person对象A,系统找不到uid:111的Person类,无法完成反序列化
  • 简单来说,就是用于反序列化时找到UID对应的类

十、随机存取文件流

10.1 概述

  • java.io.RandomAccessFile:直接继承于java.lang.Object类,实现了DataInput、DataOutput两个接口,意味着这个类 既可以读也可以写
  • 支持“随机访问” :在文件的任意地方来读、写文件
    • 支持只访问文件的部分内容
    • 可以向已存在的文件后追加内容
  • 维护标示当前读写处位置的 记录指针:记录指针可以自由移动
    • getFilePointer():获取指针位置
    • seek(long):将指针定位到指定位置。文件字节数
  • 构造器(指定对象的访问模式):RandomAccessFile(File, String)、RandomAccessFile(String, String)
    • r:以只读方式打开。不会创建文件,文件不存在会出现异常
    • rw:打开以便读取和写入
    • rwd:打开以便读取和写入;同步文件内容的更新
    • rws打开以便读取和写入;同步文件内容和元数据的更新

10.2 读写操作

/**
 * 1.直接继承于java.lang.Object类,实现了DataInput和DataOutput接口
 * 2.既可以读也可以写
 * 3.可写情况下:
 *		- 文件不存在,则创建文件
 *   	- 文件存在,对原有内容从头覆盖(不会清空)
 */
public class RandomIOTest {
    @Test
    public void test(){
        RandomAccessFile read= null;
        RandomAccessFile write= null;
        try {
            //1.文件与流的连接
            read = new RandomAccessFile("1.jpg","r");
            write = new RandomAccessFile("5.jpg","rw");
            //2.数据处理
            byte[] buf=new byte[20];
            int length;
            while((length=read.read(buf))!=-1){
                write.write(buf,0,length);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //3.关闭资源
            if (read!=null){
                try {
                    read.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (write!=null){
                try {
                    write.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    //文件存在,对原有内容从头覆盖(不会清空)
    @Test
    public void test1(){
        RandomAccessFile write= null;
        try {
            //1
            write = new RandomAccessFile("copy.txt","rw");
            //2
            write.write("abc".getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //3
            if (write!=null){
                try {
                    write.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

11.2 插入操作

/**
 * RandomAccessFile的使用
 *      - 可以通过相关的操作,实现RandomAccessFile“插入”数据的效果
 *
 * 思考:将StringBuilder替换为ByteArrayOutputStream
 */
public class InsetTest {
    @Test
    public void test(){
        RandomAccessFile raf= null;
        try {
            File file=new File("hello.txt");
            raf = new RandomAccessFile(file,"rw");
            //1.先保存指定位置的后面内容
            StringBuilder sb=new StringBuilder((int) file.length());
            raf.seek(8);
            byte[] buf=new byte[20];
            int length;
            while((length=raf.read(buf))!=-1){
                sb.append(new String(buf,0,length));
            }
            //2.在指定位置插入数据
            raf.seek(8);
            raf.write("国我爱你!".getBytes("UTF8"));
            //3.将保存的内容继续写入
            raf.write(sb.toString().getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (raf!=null){
                try {
                    raf.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
	//思考:将StringBuilder替换为ByteArrayOutputStream
    @Test
    public void test1(){
        RandomAccessFile raf= null;
        ByteArrayOutputStream baos=null;
        try {
            File file=new File("hello.txt");
            raf = new RandomAccessFile(file,"rw");
            baos =new ByteArrayOutputStream();
            //1.先保存指定位置的后面内容
            raf.seek(8);
            byte[] buf=new byte[20];
            int length;
            while((length=raf.read(buf))!=-1){
                baos.write(buf,0,length);
            }
            //2.在指定位置插入数据
            raf.seek(8);
            raf.write("国我爱你!".getBytes("UTF8"));
            //3.将保存的内容继续写入
            raf.write(baos.toString().getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (raf!=null){
                try {
                    raf.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

十一、NIO.2

概述

  • Java NIO (New IO,Non-Blocking IO)是从Java 1.4版本开始引入的一套新的IO API,可以替代标准的Java IO API。NIO与原来的IO有同样的作用和目的,但是使用的方式完全不同,NIO支持面向缓冲区的(IO是面向流的)、基于通道的IO操作。NIO将以更加高效的方式进行文件的读写操作。

  • Java API中提供了两套NIO,一套是针对标准输入输出NIO,另一套就是网络编程NIO

    |-----java.nio.channels.Channel
        |-----FileChannel:处理本地文件
        |-----SocketChannel:TCP网络编程的客户端的Channel
        |-----ServerSocketChannel:TCP网络编程的服务器端的Channel
        |-----DatagramChannel:UDP网络编程中发送端和接收端的Channel
    12345
    
  • 随着JDK 7 的发布,Java对NIO进行了极大的扩展,增强了对文件处理和文件系统特性的支持,以至于我们称他们为NIO.2。因为NIO 提供的一些功能,NIO已经成为文件处理中越来越重要的部分。

  • 早期的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.2在java.nio.file包下还提供了Files、Paths工具类,Files包含了大量静态的工具方法来操作文件;Paths则包含了两个返回Path的静态工厂方法。

Path接口

在这里插入图片描述

Paths

  • Paths 类提供的静态get() 方法用来获取Path 对象:
    • static Pathget(String first, String … more) : 用于将多个字符串串连成路径
    • static Path get(URI uri): 返回指定uri对应的Path路径

Files 类

在这里插入图片描述

在这里插入图片描述

十二、Commons

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

愿你满腹经纶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值