JavaSE高阶篇-IO流

第一部分 file类

1)File类

计算机常识:
  1.名字为".jpg"的一定是图片吗?
    不一定,有可能是文件夹
      
  2.什么叫做文本文档:
    用记事本打开,人能看懂的文件
        比如:.txt   .html .css等
             .doc -> 不是
            
  3.E:\Idea\io\1.jpg -> 1.jpg的父路径是谁?
    E:\Idea\io  
     
  4.路径分隔符:(指的是一个路径和其他路径之间的分隔符)  
    ;

    路径名称分隔符(指的是一个路径之间的分隔符  \)
    \   

 1.File类概述:
  文件和目录路径名的抽象表示形式 -> 指的就是文件或者文件夹的对象
      
2.解释:
  我们创建File对象的时候指定文件或者文件夹的路径,指定谁的路径,File就代表谁的对象
  然后我们就可以利用File对象中的方法操作指定的文件或者文件夹
  比如: File file = new File("E:\Idea\io\1.jpg")
       到时候调用File的方法就是在操作指定的1.jpg

 2)File类的静态成员

static String pathSeparator :与系统有关的路径分隔符,为了方便,它被表示为一个字符串
static String separator:与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串

public class Demo01File {
    public static void main(String[] args) {
        //static String pathSeparator :与系统有关的路径分隔符,为了方便,它被表示为一个字符串
        System.out.println(File.pathSeparator); //  ;
        //static String separator:与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串
        System.out.println(File.separator);// \
    }
}

【如何用Java正确编写一个路径?】

public class Demo01File {
 public static void main(String[] args) {
     method02();
 }

 private static void method02() {
     /*
       如果直接写\,就写的太死了
       因为:
         win: \
         linux: /

       java代码要求:一次编写,到处运行
      */
     //String path = "E:\\Idea\\io";
     String path = "E:"+File.separator+"Idea"+File.separator+"io";
     System.out.println(path);
 }
}

3)File的构造方法

File(String parent, String child) 根据所填写的路径创建File对象
     parent:父路径
     child:子路径
File(File parent, String child)  根据所填写的路径创建File对象
     parent:父路径,是一个File对象
     child:子路径
File(String pathname)  根据所填写的路径创建File对象
     pathname:直接指定路径  

public class Demo02File {
    public static void main(String[] args) {
        /*File(String parent, String child) 根据所填写的路径创建File对象
        parent:父路径
        child:子路径*/
        File file1 = new File("E:\\Idea\\io", "1.jpg");
        System.out.println(file1);
        /*File(File parent, String child)  根据所填写的路径创建File对象
        parent:父路径,是一个File对象
        child:子路径*/
        File parent = new File("E:\\Idea\\io");
        File file2 = new File(parent, "1.jpg");
        System.out.println(file2);
        /*File(String pathname)  根据所填写的路径创建File对象
        pathname:直接指定路径*/
        File file3 = new File("E:\\Idea\\io\\1.jpg");
        System.out.println(file3);
    }
}

注意:

1.创建File对象,路径可以放不存在的路径,但是直接指定的时候没有意义

但是,

 如果我们指定一个不存在的文件夹或者文件,我们可以先做判断,然后利用File中的方法去创建

 4)File的获取方法

String getAbsolutePath() -> 获取File的绝对路径->带盘符的路径
String getPath() ->获取的是封装路径->new File对象的时候写的啥路径,获取的就是啥路径
String getName()  -> 获取的是文件或者文件夹名称
long length() -> 获取的是文件的长度 -> 文件的字节数

public class Demo03File {
    public static void main(String[] args) {
        File file = new File("E:\\Idea\\io\\1.txt");
        //String getAbsolutePath() -> 获取File的绝对路径->带盘符的路径
        System.out.println("file.getAbsolutePath() = " + file.getAbsolutePath());
        //String getPath() ->获取的是封装路径->new File对象的时候写的啥路径,获取的就是啥路径
        System.out.println("file.getPath() = " + file.getPath());
        //String getName()  -> 获取的是文件或者文件夹名称
        System.out.println("file.getName() = " + file.getName());
        //long length() -> 获取的是文件的长度 -> 文件的字节数
        System.out.println("file.length() = " + file.length());
    }
}

 5)相对路径和绝对路径

1.绝对路径:
  带盘符的路径
 
  跨盘符访问可以使用绝对路径
      
2.相对路径:
  不带盘符的路径
 
  在同一个盘符下写的路径
      
3.我们现在重心在idea中怎么写相对路径:
  a.要找一个参照路径:当前project的绝对路径
  b.哪个路径为参照路径,就可以省略哪个路径,剩下的就是我们要写的相对路径
      
    比如:在模块(day19_IO)下创建一个1.txt -> 1.txt的相对路径咋写
        a.先写出1.txt的绝对路径:E:\Idea\idea2022\workspace\CD_230417Java\day19_IO\1.txt
        b.再找出参照路径:E:\Idea\idea2022\workspace\CD_230417Java
        c.哪个路径为参照路径,哪个路径就可以省略,剩下的就是相对路径:  day19_IO\1.txt  
            
4.注意:
  a.在IO部分相对路径:从模块名开始写
  b.如果直接写文件或者文件夹名,不带模块名,此时所在位置,在project下     

 6)File的创建方法

boolean createNewFile()  -> 创建文件
        如果要创建的文件之前有,创建失败,返回false
        如果要创建的文件之前没有,创建成功,返回true
    
boolean mkdirs() -> 创建文件夹(目录)既可以创建多级文件夹,还可以创建单级文件夹
        如果要创建的文件夹之前有,创建失败,返回false
        如果要创建的文件夹之前没有,创建成功,返回true

public class Demo04File {
    public static void main(String[] args) throws Exception{
        File file1 = new File("day19_IO\\1.txt");
        /*boolean createNewFile()  -> 创建文件
        如果要创建的文件之前有,创建失败,返回false
        如果要创建的文件之前没有,创建成功,返回true*/
        System.out.println(file1.createNewFile());

        /*boolean mkdirs() -> 创建文件夹(目录)既可以创建多级文件夹,还可以创建单级文件夹
        如果要创建的文件夹之前有,创建失败,返回false
        如果要创建的文件夹之前没有,创建成功,返回true*/
        File file2 = new File("E:\\Idea\\io\\haha\\hehe\\heihei\\xixi\\hiahia");
        System.out.println(file2.mkdirs());
    }
}

7)File类的删除方法

boolean delete()->删除文件或者文件夹
    
注意:
  1.如果删除文件,不走回收站
  2.如果删除文件夹,必须是空文件夹,而且也不走回收站

public class Demo05File {
    public static void main(String[] args) throws Exception{
        File file1 = new File("E:\\Idea\\io\\1.txt");
        System.out.println("file1.delete() = " + file1.delete());

        System.out.println("===============================");

        File file2 = new File("E:\\Idea\\io\\haha");
        System.out.println("file2.delete() = " + file2.delete());
    }
}

 8)File类的判断方法

boolean isDirectory() -> 判断是否为文件夹
boolean isFile()  -> 判断是否为文件
boolean exists()  -> 判断文件或者文件夹是否存在

public class Demo06File {
    public static void main(String[] args) {
        File file = new File("E:\\Idea\\io\\1.jpg");
        //boolean isDirectory() -> 判断是否为文件夹
        System.out.println("file.isDirectory() = " + file.isDirectory());
        //boolean isFile()  -> 判断是否为文件
        System.out.println("file.isFile() = " + file.isFile());
        //boolean exists()  -> 判断文件或者文件夹是否存在
        System.out.println("file.exists() = " + file.exists());
    }
}

 

9)File的遍历方法

String[] list() -> 遍历指定的文件夹,返回的是String数组
File[] listFiles()-> 遍历指定的文件夹,返回的是File数组
    
listFiles底层依靠list(),先调用list,返回String[],遍历String数组,根据遍历出来的文件或者文件夹创建File对象,然后放到File[]中   

public class Demo07File {
    public static void main(String[] args) {
        File file = new File("E:\\Idea\\io\\aa");
        //String[] list() -> 遍历指定的文件夹,返回的是String数组
        String[] list1 = file.list();
        for (String s : list1) {
            System.out.println(s);
        }
        System.out.println("=========================");
        //File[] listFiles()-> 遍历指定的文件夹,返回的是File数组
        File[] files = file.listFiles();
        for (File file1 : files) {
            System.out.println(file1);
        }
    }
}

练习1-

遍历指定文件夹下所有的.jpg文件

1.创建File对象,指明要遍历的文件夹路径
2.调用listFiles方法,遍历文件夹,返回File数组
3.遍历File数组,在遍历的过程中,判断,是否为文件
4.如果是文件,获取文件名称,判断是否以.jpg结尾,如果是,直接输出此文件
5.如果不是文件,肯定是文件夹,就继续遍历此文件夹,重复2 3 4 5的步骤

 

public class Demo08File {
    public static void main(String[] args) {
        //1.创建File对象,指明要遍历的文件夹路径
        File file = new File("E:\\Idea\\io\\aa");
        method(file);
    }

    public static void method(File file) {
        //2.调用listFiles方法,遍历文件夹,返回File数组
        File[] files = file.listFiles();
        //3.遍历File数组,在遍历的过程中,判断,是否为文件
        for (File file1 : files) {
            //4.如果是文件,获取文件名称,判断是否以.jpg结尾,如果是,直接输出此文件
            if (file1.isFile()) {
                String name = file1.getName();
                if (name.endsWith(".jpg")) {
                    System.out.println(name);
                }
            } else {
                //5.如果不是文件,肯定是文件夹,就继续遍历此文件夹,重复2 3 4 5的步骤
                method(file1);
            }

        }
    }
}

第二部分 字节流

1.IO流:
  I:Input -> 输入
  O:Output -> 输出

2.IO概述:
  将数据从一个设备上传输到另外一个设备上的技术
      
3.为啥要学IO流呢?
  a.之前学过数组,集合,都是存储数据的,但是数组和集合都是临时存储(程序运行,数据还在,运行完毕,数据消失),但是我们想的是,如何将数据永久保存,将数据保存到硬盘上就可以了
 
4.IO流操作:
  输出:将数据写到硬盘上 -> 写
  输入:将硬盘上的数据读回来 -> 读

 

1)IO流介绍以及输入输出以及流向的介绍

 四大基础类

OutputStream
 InputStream
 Writer
 Reader

  1. FileOutputStream

    • 作用: 用于将数据以字节形式写入到本地文件中。它是OutputStream的子类,专门用于文件输出操作。可以用来写入文本、二进制数据(如图像数据)或其他原始字节。
    • 特点: 创建FileOutputStream对象时,可以选择是否以追加模式打开文件(即在文件末尾添加数据而不覆盖原有内容)。默认情况下,如果不指定追加模式,写入操作会覆盖文件原有的内容。
  2. FileInputStream

    • 作用: 用于从本地文件中读取字节数据。它是InputStream的子类,专用于文件输入操作。能够读取文本、二进制数据或其他原始字节流。
    • 特点: 使用FileInputStream读取文件时,读取位置从文件起始处开始,并随着读取操作逐步推进。通常配合循环或其他手段来读取整个文件或所需部分。
  3. FileWriter

    • 作用: 用于以字符流的形式将文本数据写入到本地文件中。它是Writer的子类,特别适合处理文本数据,因为字符流能处理Unicode字符集,确保多语言文本的正确编码。
    • 特点: 默认使用系统默认的字符编码来写入文件,但也可以指定特定字符集。与FileOutputStream类似,可以选择追加模式写入文件。
  4. FileReader

    • 作用: 用于从本地文件中读取字符流形式的文本数据。它是Reader的子类,适用于处理文本文件,尤其是包含非ASCII字符的文件。
    • 特点: 同样使用系统默认的字符编码读取文件,也可以通过构造函数指定字符集。读取操作从文件起始处开始,并按需读取字符数据。
  5. BufferedOutputStream

    • 作用: 对OutputStream(如FileOutputStream)进行封装,提供缓冲机制。它内部维护一个缓冲区,将用户提供的数据暂存于缓冲区中,当缓冲区满或者用户显式调用flush()方法时,才一次性将缓冲区内容写入底层输出流。
    • 优点: 缓冲可以减少实际I/O操作次数,提高数据写入效率,尤其在处理大量小规模写入时效果显著。
  6. BufferedInputStream

    • 作用: 对InputStream(如FileInputStream)进行封装,同样提供缓冲机制。它从底层输入流中预先读取一定数量的数据到缓冲区,用户请求读取时直接从缓冲区获取,避免频繁与底层设备交互。
    • 优点: 缓冲有助于提升读取性能,减少I/O操作次数,特别是当频繁进行小规模读取时。
  7. BufferedWriter

    • 作用: 类似于BufferedOutputStream,是对Writer(如FileWriter)的缓冲封装。提供字符流级别的缓冲写入功能,优化文本数据的写入效率。
  8. BufferedReader

    • 作用: 类似于BufferedInputStream,是对Reader(如FileReader)的缓冲封装。提供字符流级别的缓冲读取功能,提高文本数据的读取速度。
  9. OutputStreamWriter

    • 作用: 将字符流(Writer)与字节流(OutputStream)关联起来,使得可以直接以字符形式写入到字节输出流中。用户指定特定字符编码,将字符数据转换为对应字节序列写入底层字节流。
  10. InputStreamReader

    • 作用: 与OutputStreamWriter相反,它将字节流(InputStream)与字符流(Reader)关联起来,允许以字符形式从字节输入流中读取数据。根据指定的字符编码,将接收到的字节序列解码为相应的字符。
  11. ObjectOutputStream

    • 作用: 用于序列化(即转换为字节流)Java对象,并将它们写入到输出流中。支持将对象的属性和状态信息保存到文件或网络流,以便后续反序列化恢复对象。常用于持久化对象数据、在网络间传递对象等场景。
  12. ObjectInputStream

    • 作用: 与ObjectOutputStream配对使用,用于从输入流中反序列化Java对象。它读取由ObjectOutputStream写出的字节流,还原为原始的Java对象及其状态。主要用于从文件或网络流中恢复先前序列化的对象。
  13. PrintStream

    • 作用: 是一种特殊的输出流,扩展了FilterOutputStream,提供了更方便的方法来输出各种类型的数据(如字符串、整数、浮点数等),并自动处理字符编码和行结束符。常见的如System.out就是PrintStream的实例。它还支持自动flush机制和错误处理。

以上这些类构成了Java I/O体系的核心组成部分,根据具体需求,开发人员可以选择合适的类来实现文件、网络或其他I/O设备上的数据读写操作。其中,带缓冲的类通常提供更好的性能,而ObjectOutputStreamObjectInputStream则用于处理对象的序列化与反序列化。PrintStream则为简单、直观的输出提供了便利。

 2)IO的流向

1.输出:从内存出发,将数据保存到硬盘上 -> 写
2.输入:将数据从硬盘上读到内存中 -> 读

 

 3)IO流的分类

字节流:按照字节操作文件-> 一切皆字节-> 字节流是万能流
    
      字节输出流:OutputStream -> 抽象类  -> 写
      字节输入流:InputStream -> 抽象类   -> 读
    
字符流:操作文本文档 -> 用记事本打开的,人能看懂的
    
      字符输出流:Writer -> 抽象类 -> 写
      字符输入流:Reader -> 抽象类 -> 读  

 

4)OutputStream中子类[FileOutputStream]的介绍以及方法的简单介绍

1.概述:

        字节输出流:FileOutputStream extends OutputStream


2.作用:将内存中的数据保存(写)到硬盘上
    
3.构造: 如果指定的文件不存在,FileOutputStream自动创建,当然不能创建文件夹
          FileOutputStream(File file) -> 根据File对象创建FileOutputStream对象
          FileOutputStream(String name) -> 根据String表示的路径创建FileOutputStream
 
4.方法:
  void write(int b) -> 一次写一个字节
  void write(byte[] b) -> 一次写一个字节数组
  void write(byte[] b, int off, int len) -> 一次写一个字节数组一部分
             b:被操作的数组
             off:从数组的哪个索引开始写
             len:写多少个
  void close() : 关闭资源 

    /**
     * void write(int b) -> 一次写一个字节
     * @throws FileNotFoundException
     */
    private static void method01() throws Exception {
        FileOutputStream fos = new FileOutputStream("day19_IO\\io\\1.txt");
        fos.write(97);
        //关流
        fos.close();
    }   
    /**
     * void write(byte[] b) -> 一次写一个字节数组
     */
    private static void method02()throws Exception {
        FileOutputStream fos = new FileOutputStream("day19_IO\\io\\1.txt");
        byte[] bytes = {97,98,99,100,101};
        fos.write(bytes);
        fos.close();
    }
    /**
     *   void write(byte[] b, int off, int len) -> 一次写一个字节数组一部分
     *              b:被操作的数组
     *              off:从数组的哪个索引开始写
     *              len:写多少个
     */
    private static void method03()throws Exception {
        FileOutputStream fos = new FileOutputStream("day19_IO\\io\\1.txt");
        byte[] bytes = {97,98,99,100,101,102};
        fos.write(bytes,0,2);
        fos.close();
    }
    private static void method04()throws Exception {
        FileOutputStream fos = new FileOutputStream("day19_IO\\io\\1.txt");
        //byte[] bytes = "你好".getBytes();//[-28, -67, -96, -27, -91, -67]
        fos.write("abcd".getBytes());
        fos.close();
    }

 5)InputStream子类[FileInputStream]的介绍以及方法的使用

 1.概述:字节输入流
  FileInputStream extends InputStream
2.作用:读数据
3.构造:
  FileInputStream(File path)
  FileInputStream(String path)
4.方法:
  int read() -> 一次读取一个字节,返回的是字符对应的字节整数
  int read(byte[] b) -> 一次读取一个字节数组,返回的是读取的个数
  int read(byte[] b, int off, int len)-> 一次读取一个字节数组一部分,返回的是读取的个数
           b:读取的数组
           off:从哪个索引开始读
           len:读多少个
  void close() : 关闭资源

6) 一次读一个字节

 

  private static void method02() throws Exception{
        FileInputStream fis = new FileInputStream("day19_IO\\io\\1.txt");
        //定义一个变量,接收读取的字节
        int len;
        while((len = fis.read())!=-1){
            //System.out.println(len);
            System.out.println((char) len);
        }
        fis.close();
    }

    /**
     * int read() -> 一次读取一个字节,返回的是字符对应的字节整数
     */
    private static void method01()throws Exception {
        FileInputStream fis = new FileInputStream("day19_IO\\io\\1.txt");
        int data1 = fis.read();
        System.out.println(data1);

        int data2 = fis.read();
        System.out.println(data2);

        int data3 = fis.read();
        System.out.println(data3);

        /*int data4 = fis.read();
        System.out.println(data4);*/
        fis.close();
    }

 1.用同一个流对象读完之后,再次读就读不出来了

2.流用完之后要关闭,关闭之后流对象就不能用了

Exception in thread "main" java.io.IOException: Stream Closed
	at java.io.FileInputStream.read0(Native Method)
	at java.io.FileInputStream.read(FileInputStream.java:207)
	at com.atguigu.b_io.Demo03FileInputStream.method01(Demo03FileInputStream.java:39)
	at com.atguigu.b_io.Demo03FileInputStream.main(Demo03FileInputStream.java:7)

 3.不要循环判断的时候read一次,然后输出时再read一次,不然输出的内容会跳着输出

 7) 读取-1问题

每个文件末尾都会有一个"标记",叫做"结束标识"

 

 8)一次读取一个字节数组以及过程

 /**
     *  int read(byte[] b) -> 一次读取一个字节数组,返回的是读取的个数
     *
     *  注意:
     *    a.字节数组定多长,每次就会读取多少个字节,数组相当于是一个临时存储空间,
     *      读到的内容会自动保存到数组中
     *    b.一般情况下,数组长度都是指定1024或者1024的倍数  
     */
    private static void method03()throws Exception {
        FileInputStream fis = new FileInputStream("day19_IO\\io\\1.txt");
        byte[] bytes = new byte[5];
        /*int len1 = fis.read(bytes);
        //System.out.println(len1);//2
        System.out.println(new String(bytes,0,len1));

        int len2 = fis.read(bytes);
        //System.out.println(len2);//2
        System.out.println(new String(bytes,0,len2));

        int len3 = fis.read(bytes);
        //System.out.println(len3);//1
        System.out.println(new String(bytes,0,len3));

        int len4 = fis.read(bytes);
        System.out.println(len4);// 读到结束标记之后返回-1*/

        //定义一个变量,接收读取的字节个数
        int len;
        while((len = fis.read(bytes))!=-1){
            System.out.println(new String(bytes,0,len));
        }
        fis.close();

    }

 9)字节流实现图片复制分析

图片复制代码实现:

package com.newio.b_io;

import java.io.FileInputStream;
import java.io.FileOutputStream;

public class Demo04Copy {
    public static void main(String[] args)throws Exception {
        FileInputStream fis = new FileInputStream("E:\\Idea\\io\\27.jpg");
        FileOutputStream fos = new FileOutputStream("E:\\Idea\\io\\upload\\27.jpg");
        //定义一个数组
        byte[] bytes = new byte[1024];
        int len;
        while((len = fis.read(bytes))!=-1){
            fos.write(bytes,0,len);
        }

        //关流-> 先开的后关
        fos.close();
        fis.close();
    }
}

 第三部分 字符流

1)字节流读取中文的问题

1.注意:字节流是万能流,侧重文件复制,但是不要边读边看(尤其是遇到中文了)
2.原因:同一个中文在不同的编码表中所占字节不一样
  GBK:一个中文占2个字节
  UTF-8:一个中文占3个字节

2)FileReader的介绍以及使用

1.概述:字符输入流
  FileReader extends Reader
2.作用:读数据
3.构造:
  FileReader(File file)
  FileReader(String path)
4.方法:
  int read() -> 一次读取一个字符
  int read(char[] cbuf) -> 一次读取一个字符数组,返回读取个数
  int read(char[] cbuf, int off, int len) -> 一次读取一个字符数组一部分,返回读取个数
  void close()->关流  

 

     /**
     * int read() -> 一次读取一个字符
     */
    private static void method01()throws Exception {
        FileReader fr = new FileReader("day19_IO\\io\\2.txt");
        /*int data1 = fr.read();
        System.out.println((char) data1);

        int data2 = fr.read();
        System.out.println((char) data2);*/

        int len;
        while((len = fr.read())!=-1){
            System.out.println((char) len);
        }

        fr.close();
    }
    /**
     * int read(char[] cbuf) -> 一次读取一个字符数组,返回读取个数
     */
    private static void method02()throws Exception {
        FileReader fr = new FileReader("day19_IO\\io\\2.txt");
        char[] chars = new char[2];
        int len;//接收的是读取的个数
        while((len = fr.read(chars))!=-1){
            System.out.println(new String(chars,0,len));
        }
        fr.close();
    }

 即使用字符流读取,如果编码不一致,依然会乱码

3)FileWriter的介绍以及使用

1.概述:字符输出流
  FileWriter extends Writer
2.作用:写数据
3.构造:
  FileWriter(File file)
  FileWriter(String path)
  FileWriter(String path,boolean append)-> 续写追加
      
4.方法:
  void write(int c)  -> 一次写一个字符
  void write(String str) -> 一次写一个字符串
  void write(char[] cbuf) -> 一次写一个字符数组
  void write(char[] cbuf, int off, int len)  -> 一次写一个字符数组一部分
  void write(String str, int off, int len) -> 一次写一个字符串一部分
  void flush() -> 刷新缓冲区    
  void close() -> 关闭资源
      
5.注意:FileWriter底层自带一个缓冲区,我们需要将缓冲区中的数据刷到文件中     

 

public class Demo06FileWriter {
    public static void main(String[] args) throws Exception{
        FileWriter fw = new FileWriter("day19_IO\\io\\3.txt");
        fw.write("李白乘舟将欲行\r\n");
        fw.write("忽闻岸上踏歌声\n");
        fw.write("桃花潭水深千尺\n");
        fw.write("不及汪伦送我情\n");
        fw.flush();
    }
}


public class Demo07FileWriter {
    public static void main(String[] args) throws Exception{
        FileWriter fw = new FileWriter("day19_IO\\io\\3.txt",true);
        fw.write("鹅鹅鹅\r\n");
        fw.write("曲项向天歌\n");
        fw.write("白毛浮绿水\n");
        fw.write("红掌拨清波\n");
        fw.flush();
    }
}

 

4)FileWriter的刷新功能和关闭功能

flush:将缓冲区中的数据刷新到文件中,后续流对象还能使用
close:先刷新,再关闭,后续流对象不能继续使用

5)IO流的异常处理方式

 

public class Demo09FileWriter {
    public static void main(String[] args) {
        FileWriter fw = null;
        try {
            fw = new FileWriter("day19_IO\\io\\3.txt");
            fw.write("你好java");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            /*
              fw如果没有new出来,就没必要close了
             */
            if (fw!=null){
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 6)jdk7后IO流的处理方式(拓展)

1.格式:
  try(IO流对象){
      可能出现异常的代码
  } catch (Exception e) {
      e.printStackTrace();
  }

2.以上异常处理方式,会自动关流

public class Demo10FileWriter {
    public static void main(String[] args) {
        try (FileWriter fw = new FileWriter("day19_IO\\io\\3.txt");) {
            fw.write("你好java");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

第四部分  字节缓冲流

1.为啥要学缓冲流:
  之前所学的FileOutputStream等流,方法都是和硬盘之间进行读写的,效率不高,缓冲流底层自带缓冲区,此时读和写都是在内存中完成的,读写效率要高
   
2.字节缓冲输出流:BufferedOutputStream
  a.构造:
    BufferedOutputStream(OutputStream out)
  b.方法:
    和FileOutputStream一样
      
3.字节缓冲输入流:BufferedInputStream
  a.构造:
    BufferedInputStream(InputStream in)
  b.方法:
    和FileInputStream一样
        
4.缓冲流底层默认有一个8192的缓冲区(数组)  

 public class Demo01BufferedOutput_BufferedInput {
    public static void main(String[] args)throws Exception {
        //copy1();
        copy2();
    }

    /**
     * 用缓冲流复制
     * @throws Exception
     */
    private static void copy2()throws Exception {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\Idea\\io\\upload\\1.avi"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\Idea\\io\\upload\\2.avi"));
        long start = System.currentTimeMillis();

        //定义一个数组
        byte[] bytes = new byte[1024];
        int len;
        while((len = bis.read(bytes))!=-1){
            bos.write(bytes,0,len);
        }

        long end = System.currentTimeMillis();

        System.out.println((end-start)+"毫秒");

        //关流-> 先开的后关
        bos.close();
        bis.close();
    }

    /**
     * 用普通流复制一个视频
     */
    private static void copy1()throws Exception {
        FileInputStream fis = new FileInputStream("E:\\Idea\\io\\upload\\1.avi");
        FileOutputStream fos = new FileOutputStream("E:\\Idea\\io\\upload\\2.avi");

        long start = System.currentTimeMillis();

        //定义一个数组
        byte[] bytes = new byte[1024];
        int len;
        while((len = fis.read(bytes))!=-1){
            fos.write(bytes,0,len);
        }

        long end = System.currentTimeMillis();

        System.out.println((end-start)+"毫秒");

        //关流-> 先开的后关
        fos.close();
        fis.close();
    }
}

 第五部分 字符缓冲流

1)字符缓冲输出流_BufferedWriter

1.概述:BufferedWriter extends Writer
2.构造:
  BufferedWriter(Writer w)
3.方法:
  和FileWriter一样
4.特有方法:
  void newLine() -> 换行

public class Demo02BufferedWriter {
    public static void main(String[] args)throws Exception {
        BufferedWriter bw = new BufferedWriter(new FileWriter("day20_IO\\io\\bufferedwriter.txt"));
        bw.write("枯藤老树昏鸦");
        bw.newLine();
        bw.write("小桥流水人家");
        bw.newLine();
        bw.write("古道西风瘦马");
        bw.newLine();
        bw.write("夕阳西下,断肠人在天涯");
        bw.newLine();
        bw.close();
    }
}

 2)字符缓冲输入流_BufferedReader

 1.概述:BufferedReader extends Reader
2.构造:
  BufferedReader(Reader r)
3.方法:
  和FileReader一样
4.特有方法:
  String readLine()一次读一行

 

public class Demo03BufferedReader {
    public static void main(String[] args)throws Exception {
        BufferedReader br = new BufferedReader(new FileReader("day20_IO\\io\\bufferedwriter.txt"));
        /*String s1 = br.readLine();
        System.out.println("s1 = " + s1);

        String s2 = br.readLine();
        System.out.println("s2 = " + s2);

        String s3 = br.readLine();
        System.out.println("s3 = " + s3);

        String s4 = br.readLine();
        System.out.println("s4 = " + s4);*/

        String line;
        while((line = br.readLine())!=null){
            System.out.println(line);
        }
        
        br.close();
    }
}

3)字符缓冲流练习

将in.txt中的内容排好序,写到另外一个新文件中

c.侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下。愚以为宫中之事,事无大小,悉以咨之,然后施行,必得裨补阙漏,有所广益。
h.愿陛下托臣以讨贼兴复之效,不效,则治臣之罪,以告先帝之灵。若无兴德之言,则责攸之、祎、允等之慢,以彰其咎;陛下亦宜自谋,以咨诹善道,察纳雅言,深追先帝遗诏,臣不胜受恩感激。
d.将军向宠,性行淑均,晓畅军事,试用之于昔日,先帝称之曰能,是以众议举宠为督。愚以为营中之事,悉以咨之,必能使行阵和睦,优劣得所。
b.宫中府中,俱为一体,陟罚臧否,不宜异同。若有作奸犯科及为忠善者,宜付有司论其刑赏,以昭陛下平明之理,不宜偏私,使内外异法也。
a.先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。
i.今当远离,临表涕零,不知所言。
f.臣本布衣,躬耕于南阳,苟全性命于乱世,不求闻达于诸侯。先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之中,咨臣以当世之事,由是感激,遂许先帝以驱驰。后值倾覆,受任于败军之际,奉命于危难之间,尔来二十有一年矣。
g.先帝知臣谨慎,故临崩寄臣以大事也。受命以来,夙夜忧叹,恐付托不效,以伤先帝之明,故五月渡泸,深入不毛。今南方已定,兵甲已足,当奖率三军,北定中原,庶竭驽钝,攘除奸凶,兴复汉室,还于旧都。此臣所以报先帝而忠陛下之职分也。至于斟酌损益,进尽忠言,则攸之、祎、允之任也。
e.亲贤臣,远小人,此先汉所以兴隆也;亲小人,远贤臣,此后汉所以倾颓也。先帝在时,每与臣论此事,未尝不叹息痛恨于桓、灵也。侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之信之,则汉室之隆,可计日而待也。

 步骤:
  1.创建一个ArrayList集合,用于保存读取到的内容,进行排序
  2.创建BufferedReader,用于读取每一行数据
  3.创建BufferedWriter,将读取到的内容写到out.txt中
  4.边读,边往Arraylist集合中存
  5.利用Collections.sort进行排序
  6.遍历集合,边遍历边写到out.txt中

public class Demo04Copy {
    public static void main(String[] args) throws Exception{
        //1.创建一个ArrayList集合,用于保存读取到的内容,进行排序
        ArrayList<String> list = new ArrayList<>();
        //2.创建BufferedReader,用于读取每一行数据
        BufferedReader br = new BufferedReader(new FileReader("day20_IO\\io\\in.txt"));
        //3.创建BufferedWriter,将读取到的内容写到out.txt中
        BufferedWriter bw = new BufferedWriter(new FileWriter("day20_IO\\io\\out.txt"));
        //4.边读,边往Arraylist集合中存
        String line;
        while((line = br.readLine())!=null){
            list.add(line);
        }
        //5.利用Collections.sort进行排序
        Collections.sort(list);
        //6.遍历集合,边遍历边写到out.txt中
        for (String s : list) {
            bw.write(s);
            bw.newLine();
        }

        bw.close();
        br.close();
    }
}

 

第六部分 转换流

1)字符编码

计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的数字、英文、标点符号、汉字等字符是二进制数转换之后的结果。[按照某种规则,将字符存储到计算机中,称为编码] 。反之,将存储在计算机中的二进制数按照某种规则解析显示出来,称为解码 。比如说,按照A规则存储,同样按照A规则解析,那么就能显示正确的文本f符号。反之,按照A规则存储,再按照B规则解析,就会导致乱码现象。

 

 2)字符集

字符集 Charset:也叫编码表。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。

计算机要准确的存储和识别各种字符集符号,需要进行字符编码,一套字符集必然至少有一套字符编码。常见字符集有ASCII字符集、GBK字符集、Unicode字符集等。

 

 

  • ASCII字符集 :

    • ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,用于显示现代英语,主要包括控制字符(回车键、退格、换行键等)和可显示字符(英文大小写字符、阿拉伯数字和西文符号)。

    • 基本的ASCII字符集,使用7位(bits)表示一个字符,共128字符。ASCII的扩展字符集使用8位(bits)表示一个字符,共256字符,方便支持欧洲常用字符。

  • ISO-8859-1字符集:

    • 拉丁码表,别名Latin-1,用于显示欧洲使用的语言,包括荷兰、丹麦、德语、意大利语、西班牙语等。

    • ISO-8859-1使用单字节编码,兼容ASCII编码。

  • GBxxx字符集:

    • GB就是国标的意思,是为了显示中文而设计的一套字符集。

    • GB2312:简体中文码表。一个小于127的字符的意义与原来相同。但两个大于127的字符连在一起时,就表示一个汉字,这样大约可以组合了包含7000多个简体汉字,此外数学符号、罗马希腊的字母、日文的假名们都编进去了,连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。

    • GBK:最常用的中文码表。是在GB2312标准基础上的扩展规范,使用了双字节编码方案,共收录了21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等。

    • GB18030:最新的中文码表。收录汉字70244个,采用多字节编码,每个字可以由1个、2个或4个字节组成。支持中国国内少数民族的文字,同时支持繁体汉字以及日韩汉字等。

  • Unicode字符集

    • Unicode编码系统为表达任意语言的任意字符而设计,是业界的一种标准,也称为统一码、标准万国码。

    • 它最多使用4个字节的数字来表达每个字母、符号,或者文字。有三种编码方案,UTF-8、UTF-16和UTF-32。最为常用的UTF-8编码。

    • UTF-8编码,可以用来表示Unicode标准中任何字符,它是电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。所以,我们开发Web应用,也要使用UTF-8编码。它使用一至四个字节为每个字符编码,编码规则:

      1. 128个US-ASCII字符,只需一个字节编码。

      2. 拉丁文等字符,需要二个字节编码。

      3. 大部分常用字(含中文),使用三个字节编码。

      4. 其他极少使用的Unicode辅助字符,使用四字节编码。

 1.存储的过程就是编码的过程
  读取的过程就是解码的过程
2.注意:
  a.编码和解码必须遵循的是同一个字符集,不然会乱码
3.一个汉字在UTF-8编码中占3个字节
  一个汉字在GBK编码中占2个字节

3)转换流_InputStreamReader

1.概述:字节流通向字符流的桥梁 ->读取
2.构造:
  InputStreamReader(InputStream in, String charsetName)
                                    charsetName:指定字符集,不区分大小写
3.用法:
  和FileReader一样

public class Demo01InputStreamReader {
    public static void main(String[] args)throws Exception {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("E:\\Idea\\io\\upload\\1.txt"),"gbk");
        int data = isr.read();
        System.out.println((char)data);
        isr.close();
    }
}

4)转换流_OutputStreamWriter

 1.概述:OutputStreamWriter extends Writer ->  字符流通向字节流的桥梁
 2.构造:
   OutputStreamWriter(OutputStream out, String charsetName)
                      out:抽象类,传递子类对象
                      charsetname:指定字符编码
 3.方法:和FileWriter一样 

public class Demo02OutputStreamWriter {
    public static void main(String[] args)throws Exception {
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("E:\\Idea\\io\\upload\\2.txt"),"GBK");
        osw.write("你");
        osw.close();
    }
}

 

第七部分 序列化流

1)序列化流与反序列化流介绍

(1)Java序列化就是指把Java对象转换为字节序列的过程
   Java反序列化就是指把字节序列恢复为Java对象的过程。

(2)序列化最重要的作用:在传递和保存对象时.保证对象的完整性和可传递性。对象转换为有序字节流,以便在网络上传输或者保存在本地文件中。

 

2)序列化流_ObjectOutputStream

1.作用:写对象
2.构造:
  ObjectOutputStream(OutputStream out)
3.方法:
  writeObject(对象)
4.注意:想要将对象进行序列化,需要实现Serializable接口 

    /**
     * 序列化:ObjectOutputStream
     */
    private static void write()throws Exception {
        ObjectOutputStream oos =
                new ObjectOutputStream(new FileOutputStream("day20_IO\\io\\object.txt"));
        oos.writeObject(new Person("张三",18));
        oos.close();
    }

 

  public class Person implements Serializable {
    private String name;
    private Integer age;

    public Person() {
    }

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

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

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

 

3)反序列化_ObjectInputStream

1.作用:读对象
2.构造:
  ObjectInputStream(InputStream in)
3.方法:
  Object readObject()

 

    /**
     * 反序列化:ObjectInputStream
     */
    private static void read()throws Exception {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day20_IO\\io\\object.txt"));
        Object o = ois.readObject();
        System.out.println(o);
        ois.close();
    }

4)不想被反序列化操作(了解)

1.在数据前面加关键字:
  transient

 5)反序列化时出现的问题以及分析以及解决(扩展)

.问题描述:
  序列化之后,我们修改源码,修改完之后没有重新序列化,直接反序列化,就会出现序列号冲突问题

 

 

public class Person implements Serializable {
    static final long serialVersionUID = 42L;
    private String name1;
    public Integer age;

    public Person() {
    }

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

    public String getName() {
        return name1;
    }

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

    public Integer getAge() {
        return age;
    }

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

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

 

public class Demo01Object {
    public static void main(String[] args)throws Exception {
        write();
        read();
    }

    /**
     * 反序列化:ObjectInputStream
     */
    private static void read()throws Exception {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day20_IO\\io\\object.txt"));
        Object o = ois.readObject();
        System.out.println(o);
        ois.close();
    }

    /**
     * 序列化:ObjectOutputStream
     */
    private static void write()throws Exception {
        ObjectOutputStream oos =
                new ObjectOutputStream(new FileOutputStream("day20_IO\\io\\object.txt"));
        oos.writeObject(new Person("张三",18));
        oos.close();
    }
}

6)经验问题

EOFException: 文件意外到达结尾异常
    
        出现原因:反序列化的时候,次数和保存到文件中的对象个数不一样

-----------------------------------------------------------------------------------------------------------------------

解决方法:
  将多个对象放到集合中,然后序列化这个集合

 第八部分  打印流_PrintStream(了解)

1)PrintStream打印流基本使用

 1.构造:
  PrintStream(String fileName)
2.方法:
  println()原样输出,自带换行效果
  print() 原样输出,不换行

public class Demo01PrintStream {
    public static void main(String[] args)throws Exception {
        PrintStream ps = new PrintStream("day20_IO\\io\\print.txt");
        ps.println("白日依山尽");
        ps.println("黄河入海流");
        ps.println("欲穷千里目");
        ps.println("更上一层楼");
        ps.close();
    }
}

 扩展:改变流向
 
1.什么叫做改变流向:
  System.out.println()->本身是输出到控制台上的
  改变流向:可以让输出语句从控制台上输出改变成往指定文件中输出
      
2.方法:System类中的方法
      static void setOut(PrintStream out) -> 改变流向-> 让输出语句从控制台输出转移到指定文件中
    
3.作用:
  配合日志文件使用,可以将输出语句中的内容放到日志文件中保存起来
      
  以后我们希望将输出的内容永久保存,但是输出语句将结果输出到控制台上,是临时显示;所以我们需要将输出的结果保存到日志文件中,就可以用setOut改变流向

public class Demo02PrintStream {
    public static void main(String[] args)throws Exception {
        PrintStream ps = new PrintStream("day20_IO\\io\\log.txt");
        System.setOut(ps);
        System.out.println("门前大桥下,游过一群鸭");
        ps.close();
    }
}

 2)PrintStream打印流完成续写

PrintStream(OutputStream out)

public class Demo03PrintStream {
    public static void main(String[] args)throws Exception {
        PrintStream ps = new PrintStream(new FileOutputStream("day20_IO\\io\\printstream.txt",true));
        ps.println("火大了火大了,饺子破了");
        ps.println("饺子破没法吃怎么办呀?");
        ps.println("皮儿在外馅儿在内那是饺子");
        ps.println("皮儿在内馅儿在外那是披萨");
        ps.close();
    }
}

 第九部分  Properties集合

1)Properties结合IO流使用方法

1.Properties概述:是Hashtable的子类
2.特点:
  a.key唯一,value可重复
  b.无序
  c.无索引
  d.线程安全
  e.key和value都是默认String
3.特有方法:
  setProperty(String key,String value) 存键值对
  getProperty(String key) 根据key获取value
  stringPropertyNames()获取所有的key存到set集合中
  load(InputStream in)将流中的数据装载到Properties集合中

public class Demo01Properties {
    public static void main(String[] args) {
        Properties properties = new Properties();
        properties.setProperty("username","tom");
        properties.setProperty("password","1234");

        Set<String> set = properties.stringPropertyNames();
        for (String key : set) {
            String value = properties.getProperty(key);
            System.out.println(key+"..."+value);
        }
    }
}

 1.问题描述:
  很多数据直接放到源码中不太合适,如果我们要修改这些数据,就要去源码中修改,类和类之间有联系,有可能改完之后有问题了
      
2.解决:
  将这些硬数据放到文件中,然后动态解析文件(配置文件),动态获取文件中的数据,到时候想修改数据,我们直接去文件中改,不用频繁修改源代码了
      
3.使用:
   load(InputStream in)将流中的数据装载到Properties集合中
       
4.Properties的使用场景:
  配合配置文件使用
      
5.怎么创建properties配置文件:
  a.右键->file
  b.取名字:xxx.properties

 properties配置文件的配置要求:
  1.必须是key=value形式
  2.每一个键值对写完要换行写下一对
  3.尽量不要写中文
  4.key和value都是String的,但是不要加""
  5.不要有空格  

username=root
password=1234

 

public class Demo02Properties {
    public static void main(String[] args)throws Exception {
        FileInputStream in = new FileInputStream("day20_IO\\pro.properties");
        Properties properties = new Properties();
        properties.load(in);

        Set<String> set = properties.stringPropertyNames();
        for (String key : set) {
            String value = properties.getProperty(key);
            System.out.println(key+"..."+value);
        }
    }
}

第十部分 Commons-io工具包

1)介绍

IO技术开发中,代码量很大,而且代码的重复率较高。如果我们要遍历目录,拷贝目录就需要使用方法的递归调用,也增大了程序的复杂度。

Apache软件基金会,开发了IO技术的工具类`commonsIO`,大大简化IO开发。

 2)添加第三方 jar包

1.Apache软件基金会属于第三方(Oracle公司是第一方,我们自己是第二方,其他的都是第三方)我们要使用第三方开发号的工具,需要添加jar包
    
2.jar包介绍:属于一个压缩包,里面装的都是class文件
           我们想使用jar包中开发好的API,我们需要将jar引入到我们当前项目环境下
    
3.怎么引入jar包:
  a.在当前模块下创建一个文件夹,取名为lib或者libs
  b.将jar包复制到lib下
  c.将jar包解压到当年项目环境下
    对着lib右键 -> add as library -> ok

3)工具包的使用

IOUtils类
- 静态方法:IOUtils.copy(InputStream in,OutputStream out)传递字节流,实现文件复制。
- 静态方法:IOUtils.closeQuietly(任意流对象)悄悄的释放资源,自动处理close()方法抛出的异常。

 

public class Demo01IOUtils {
    public static void main(String[] args) {
        //- 静态方法:IOUtils.copy(InputStream in,OutputStream out)传递字节流,实现文件复制。
        //IOUtils.copy(new FileInputStream("E:\\Idea\\io\\1.jpg"),new FileOutputStream("E:\\Idea\\io\\柳岩.jpg"));

        //- 静态方法:IOUtils.closeQuietly(任意流对象)悄悄的释放资源,自动处理close()方法抛出的异常。
        FileWriter fw = null;
        try {
            fw = new FileWriter("day20_IO\\io\\commons.txt");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //fw.close();
            if (fw != null) {
                IOUtils.closeQuietly(fw);
            }
        }
    }
}

 FileUtils类

- 静态方法:FileUtils.copyDirectoryToDirectory(File src,File dest);
           传递File类型的目录,进行整个目录的复制,自动进行递归遍历。
           
           参数:
             src:要复制的文件夹路径
             dest:要将文件夹粘贴到哪里去
             
- 静态方法:writeStringToFile(File file,String str)写字符串到文本文件中。
- 静态方法:String readFileToString(File file)读取文本文件,返回字符串。

public class Demo01FileUtils {
    public static void main(String[] args) throws IOException {
        //- 静态方法:FileUtils.copyDirectoryToDirectory(File src,File dest);
        //传递File类型的目录,进行整个目录的复制,自动进行递归遍历。
        //参数:
        //src:要复制的文件夹路径
        //dest:要将文件夹粘贴到哪里去
        //FileUtils.copyDirectoryToDirectory(new File("E:\\Idea\\io\\aa"),new File("E:\\Idea\\io\\bb"));

        //- 静态方法:writeStringToFile(File file,String str)写字符串到文本文件中。
        //FileUtils.writeStringToFile(new File("day20_IO\\io\\commons.txt"),"hahah");

        //- 静态方法:String readFileToString(File file)读取文本文件,返回字符串。
        String s = FileUtils.readFileToString(new File("day20_IO\\io\\commons.txt"));
        System.out.println(s);
    }
}

第十一部分 Lombok

1)基本介绍

1.作用:简化javabean
2.使用:
  a.导jar包
  b.下插件

 

Lombok通过增加一些“处理程序”,可以让java变得简洁、快速。

Lombok能以注解形式来简化java代码,提高开发效率。开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护。

Lombok能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法。出现的神奇就是在源码中没有getter和setter方法,但是在编译生成的字节码文件中有getter和setter方法。这样就省去了手动重建这些代码的麻烦,使代码看起来更简洁些。

 

 2)常用注解

@Getter和@Setter

  • 作用:生成成员变量的get和set方法。

  • 写在成员变量上,指对当前成员变量有效。

  • 写在类上,对所有成员变量有效。

  • 注意:静态成员变量无效。

 

 

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
    private String name;
    private Integer age;
}

public class Test01 {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("柳岩");
        person.setAge(36);
        System.out.println(person.getName()+"..."+person.getAge());
        System.out.println(person);
        System.out.println("======================");

        Person person1 = new Person("曼曼", 18);
        System.out.println(person1);
    }
}

第十二部分 正则表达式

1)正则表达式的概念以及演示

1.概述:
  就是一个具有特殊规则的字符串
2.作用:
  用于校验规则
3.如何判断输入的字符串是否符合正则表达式
  boolean matches(String regex)-> regex代表的是正则表达式
4.需求:校验一个QQ号
       a.不能0开头
       b.必须都是数字
       c.必须是5-15位

public class Demo01Regex {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String data = sc.next();
        //boolean result = method(data);
        //System.out.println("result = " + result);

        System.out.println("======================");

        boolean result1 = method02(data);
        System.out.println("result1 = " + result1);
    }

    private static boolean method02(String data) {
        boolean result = data.matches("[1-9][0-9]{4,14}");
        return result;
    }

    private static boolean method(String data) {
        //a.不能0开头
        if (data.startsWith("0")){
            return false;
        }
        //b.必须都是数字
        char[] chars = data.toCharArray();
        for (char aChar : chars) {
            if (aChar<'0' || aChar>'9'){
                return false;
            }
        }
        //c.必须是5-15位
        if (data.length()<5 || data.length()>15){
            return false;
        }
        return true;
    }
}

2)正则表达式-字符类

java.util.regex.Pattern:正则表达式的编译表示形式。
    正则表达式-字符类:[]表示一个区间,范围可以自己定义
        语法示例:
        1. [abc]:代表a或者b,或者c字符中的一个。
        2. [^abc]:代表除a,b,c以外的任何字符。
        3. [a-z]:代表a-z的所有小写字符中的一个。
        4. [A-Z]:代表A-Z的所有大写字符中的一个。
        5. [0-9]:代表0-9之间的某一个数字字符。
        6. [a-zA-Z0-9]:代表a-z或者A-Z或者0-9之间的任意一个字符。
        7. [a-dm-p]:a 到 d 或 m 到 p之间的任意一个字符     

public class Demo02Regex {
    public static void main(String[] args) {
        //1.验证字符串是否以h开头,d结尾,中间是aeiou的某一个字符
        boolean result01 = "had".matches("[h][aeiou][d]");
        System.out.println("result01 = " + result01);
        //2.验证字符串是否以h开头,d结尾,中间不是aeiou的某一个字符
        boolean result02 = "had".matches("[h][^aeiou][d]");
        System.out.println("result02 = " + result02);
        //3.验证字符串是否是开头a-z的任意一个小写字母,后面跟ad
        boolean result03 = "had".matches("[a-z][a][d]");
        System.out.println("result03 = " + result03);
    }
}

 3)正则表达式-逻辑运算符

/**
 正则表达式-逻辑运算符
        语法示例:
        1. &&:并且
        2. | :或者 
**/

public class Demo03Regex {
    public static void main(String[] args) {
        //1.要求字符串是小写a-z的任意字符,并且字符不能以[aeiou]开头,后面跟ad
        boolean result01 = "aad".matches("[[a-z]&&[^aeiou]][a][d]");
        System.out.println("result01 = " + result01);

        //2.要求字符串是aeiou中的某一个字母开头,后跟ad
        boolean result02 = "aad".matches("[a|e|i|o|u][a][d]");
        System.out.println("result02 = " + result02);
    }
}

 4)正则表达式0-预定义字符

 /**
正则表达式-预定义字符
    语法示例:
    1. "." : 匹配任何字符。(重点)  不能加[]
    2. "\\d":任何数字[0-9]的简写;(重点)
    3. "\\D":任何非数字[^0-9]的简写;
    4. "\\s": 空白字符:[ \t\n\x0B\f\r] 的简写
    5. "\\S": 非空白字符:[^\s] 的简写
    6. "\\w":单词字符:[a-zA-Z_0-9]的简写(重点)
    7. "\\W":非单词字符:[^\w]
**/

public class Demo04Regex {
    public static void main(String[] args) {
        //1.验证字符串是否是三位数字
        //boolean result01 = "111".matches("[0-9][0-9][0-9]");
        boolean result01 = "111".matches("\\d\\d\\d");
        System.out.println("result01 = " + result01);

        //2.验证手机号:1开头 第二位3 5 8 剩下的9位都是0-9的数字
        boolean result02 = "13838381438".matches("[1][358]\\d\\d\\d\\d\\d\\d\\d\\d\\d");
        System.out.println("result02 = " + result02);

        //3.验证字符串是否以h开头,d结尾,中间是任意一个字符
        boolean result03 = "had".matches("[h].[d]");
        System.out.println("result03 = " + result03);
    }
}

5)正则表达式-数量词

/**
 正则表达式-数量词
        语法示例:x代表字符
        1. X? : x出现的数量为 0次或1次
        2. X* : x出现的数量为 0次到多次 任意次
        3. X+ : x出现的数量为 1次或多次 X>=1次
        4. X{n} : x出现的数量为 恰好n次 X=n次
        5. X{n,} : x出现的数量为 至少n次 X>=n次  x{3,}
        6. X{n,m}: x出现的数量为 n到m次(n和m都是包含的)   n=<X<=m
**/

public class Demo05Regex {
    public static void main(String[] args) {
        //1.验证字符串是否是三位数字
        boolean result01 = "1111".matches("\\d{3}");
        System.out.println("result01 = " + result01);

        //2.验证手机号:1开头 第二位3 5 8 剩下的9位都是0-9的数字
        boolean result02 = "13838381438".matches("[1][358]\\d{9}");
        System.out.println("result02 = " + result02);

        //3.验证qq号:不能是0开头   都是数字    5-15
        boolean result03 = "1212121".matches("[1-9][0-9]{4,14}");
        System.out.println("result03 = " + result03);
    }
}

6)正则表达式-分组括号()

public class Demo06Regex {
    public static void main(String[] args) {
        //校验字符串abc可以出现任意次
        boolean result01 = "abcabcabca".matches("(abc)*");
        System.out.println("result01 = " + result01);
    }
}

7)String类中和正则表达式相关的方法

/**
 String类中和正则表达式相关的方法
        boolean matches(String regex) 判断字符串是否匹配给定的正则表达式。
        String[] split(String regex) 根据给定正则表达式的匹配拆分此字符串。
        String replaceAll(String regex, String replacement)把满足正则表达式的字符串,替换为新的字符
**/

public class Demo07Regex {
    public static void main(String[] args) {
        String s = "abc dfad  sadfasdf   a";
        String[] arr = s.split(" +");
        System.out.println(Arrays.toString(arr));

        System.out.println("=================");

        //String replaceAll(String regex, String replacement)把满足正则表达式的字符串,替换为新的字符

        String s1 = "abc adfa  sadfads    dfdsa  dsaf";
        String newStr = s1.replaceAll(" +", "z");
        System.out.println("newStr = " + newStr);
    }
}


8)正则表达式生成

https://www.sojson.com/regex/generate

IO 流总结

 写的不好的,希望看到这边的人给我指出来,谢谢读者!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/553519.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何安装 IntelliJ IDEA 最新版本——详细教程

IntelliJ IDEA 简称 IDEA&#xff0c;被业界公认为最好的 Java 集成开发工具&#xff0c;尤其在智能代码助手、代码自动提示、代码重构、代码版本管理(Git、SVN、Maven)、单元测试、代码分析等方面有着亮眼的发挥。IDEA 产于捷克&#xff0c;开发人员以严谨著称的东欧程序员为主…

vscode 搭建stm32开发环境记录(eide+cortex-debug+jlink)

前言 clion使用的快过期了&#xff0c;所以就准备使用vscode 来代替clion作为代码开发环境 vscode 插件安装 创建个空白工程 添加项目相关的源文件&#xff0c;和配置宏定义和头文件目录 编译和烧录(ok) 结合cortex-debug 结果(测试ok)

数据可视化-ECharts Html项目实战(13)

在之前的文章中&#xff0c;我们深入学习ECharts动态主题切换和自定义ECharts主题。想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&#xff0c;请留下你宝贵的点赞&#xff0c;谢谢。 数据可视化-ECharts Html项…

Linux执行命令监控详细实现原理和使用教程,以及相关工具的使用

Linux执行命令监控详细实现原理和使用教程&#xff0c;以及相关工具的使用。 0x00 背景介绍 Linux上的HIDS需要实时对执行的命令进行监控&#xff0c;分析异常或入侵行为&#xff0c;有助于安全事件的发现和预防。为了获取执行命令&#xff0c;大致有如下方法&#xff1a; 遍…

MySQL-笔记-06.数据高级查询

目录 6.1 连接查询 6.1.1 交叉连接&#xff08;cross join&#xff09; 6.1.2 内连接&#xff08;inner join&#xff09; 6.1.3 外连接&#xff08;outer join&#xff09; 6.1.3.1 左外连接&#xff08;left [outer] join&#xff09; 6.1.3.2 右外连接&#xff08;rig…

第2章:车辆纵向控制

2.1 车辆纵向动力学模型 注&#xff1a;车辆的纵向控制是指控制车辆行驶方向上的加减速&#xff0c;使得汽车可以按照期望的速度行驶&#xff0c;并保持安全的前后车距&#xff08;即对汽车油门 / 刹车的控制&#xff09;&#xff1b; 2.1.1 车辆纵向受力模型 &#xff1a;轮胎…

SpringBootSpringCloud升级可能会出现的问题

1.背景 之前负责过我们中台的SpringBoot和Cloud的升级&#xff0c;特次记录分享一下项目中可能出现的问题&#xff0c;方便后续的人快速定位问题。以及下述选择的解决方案都是基于让升级的服务影响和改动最小以及提供通用的解决方案的提前进行选择的。 1.1版本说明 升级前&a…

OpenCV基本图像处理操作(十)——图像特征harris角点

角点 角点是图像中的一个特征点&#xff0c;指的是两条边缘交叉的点&#xff0c;这样的点在图像中通常表示一个显著的几角。在计算机视觉和图像处理中&#xff0c;角点是重要的特征&#xff0c;因为它们通常是图像中信息丰富的区域&#xff0c;可以用于图像分析、对象识别、3D…

JavaSE中的String类

1.定义方式 常见的三种字符串构造 public class Test1 {public static void main(String[] args) {// 使用常量串构造String str1 "abc";System.out.println(str1);// 直接newString对象String str2 new String("ABC");System.out.println(str2);// 使用…

【Linux学习】Linux指令(四)

文章标题 &#x1f680;zip/unzip指令&#xff1a;&#x1f680;tar指令&#xff08;重要&#xff09;&#xff1a;&#x1f680;uname –r指令&#xff1a;&#x1f680;关机指令&#x1f680;几个常用操作 &#x1f680;zip/unzip指令&#xff1a; zip 与 unzip的安装 yum i…

Day20-【Java SE高级】单元测试 反射 注解 动态代理

一、单元测试 就是针对最小的功能单元(方法)&#xff0c;编写测试代码对其进行正确性测试。 1. 咱们之前是如何进行单元测试的?有啥问题? 只能在main方法编写测试代码&#xff0c;去调用其他方法进行测试。无法实现自动化测试&#xff0c;一个方法测试失败&#xff0c;可能…

学习在Debian系统上安装Shadowsocks教程

学习在Debian系统上安装Shadowsocks教程 安装shadowsocks-libev及其所需的依赖启动Shadowsocks服务&#xff1a;如果你想要通过代理本地流量&#xff0c;你可以使用ss-local&#xff1a;启动并设置ss-local&#xff1a;查看状态本地连接 安装shadowsocks-libev及其所需的依赖 …

量化交易为什么独宠Python

“我在学一门叫Python的语言”。“什么是Python&#xff0c;没听说过啊&#xff0c;为什么不学C啊”。这是发生在2014年&#xff0c;上海的一家量化基金&#xff0c;量化研究员和老板之间的对话。 “我想问一下关于Python的课程&#xff0c;什么时候能开班”。“Python啊&#…

数据结构-栈和队列刷题集(长期更新)

文章目录 万能计算器的实现以及源码分析1. leetcode 150 逆波兰表达式求值 万能计算器的实现以及源码分析 /*** 我们尝试写一个完整版的计算器,由于计算机不能很好的识别括号,所以一般要转换为逆波兰表达式求解* 思路解析 :* 1. 输入一个 中缀表达式* 2. 中缀表达式转化为list…

Python 数据结构和算法实用指南(一)

原文&#xff1a;zh.annas-archive.org/md5/66ae3d5970b9b38c5ad770b42fec806d 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 前言 数据结构和算法是信息技术和计算机科学工程学习中最重要的核心学科之一。本书旨在提供数据结构和算法的深入知识&#xff0c;以及编程…

28岁转行嵌入式适合转嵌入式吗?

转行到嵌入式领域是一个很好的选择&#xff0c;特别是如果你对电子技术、嵌入式系统和软硬件交互感兴趣的话。我这里有一套嵌入式入门教程&#xff0c;不仅包含了详细的视频 讲解&#xff0c;项目实战。如果你渴望学习嵌入式&#xff0c;不妨点个关注&#xff0c;给个评论222&a…

信息系统项目管理师0054:运维和服务(4信息系统管理—4.1管理方法—4.1.4运维和服务)

点击查看专栏目录 文章目录 4.1.4运维和服务1.运行管理和控制2.IT服务管理3.运行与监控4.终端侧管理5.程序库管理6.安全管理7.介质控制8.数据管理4.1.4运维和服务 信息系统的运维和服务应从信息系统运行的视角进行整合性的统筹规划,包括对信息系统、应用程序和基础设施的日常控…

C语言的OJ判题机设计与实现

1. 接收判题入参 判题需要作答代码、测试输入和期望输出、编译器名称、时空限制。对于支持special judge的还需要传入是否为sj和sj代码。推荐使用消息队列&#xff0c;应对高并发的比赛情况会比较好。 但是消息队列是异步的&#xff0c;我为了快点实现能提交后在当前页面获得判…

Elasticsearch:(一)ES简介

搜索引擎是什么&#xff1f;在不少开发者眼中&#xff0c;ES似乎就是搜索引擎的代名词&#xff0c;然而这实际上是一种误解。搜索引擎是一种专门用于从互联网中检索信息的技术工具&#xff0c;它主要可以划分为元搜索引擎、全文搜索引擎和垂直搜索引擎几大类。其中&#xff0c;…

AIGC算法1:Layer normalization

1. Layer Normalization μ E ( X ) ← 1 H ∑ i 1 n x i σ ← Var ⁡ ( x ) 1 H ∑ i 1 H ( x i − μ ) 2 ϵ y x − E ( x ) Var ⁡ ( X ) ϵ ⋅ γ β \begin{gathered}\muE(X) \leftarrow \frac{1}{H} \sum_{i1}^n x_i \\ \sigma \leftarrow \operatorname{Var}(…
最新文章