java中异常和IO流的详解

一 异常
1.1
异常:就是程序出现的不正常的情况。

举例:

  • 异常:
  • 错误:这是非常严重的问题,一般我们处理不了,一般在这里指的是硬件问题。
  • 异常:
  • 编译时期异常 开始就必须要处理的,如果不处理,后面就走不了。
  • 运行时期异常 开始可以不用处理。这种问题一旦发生,就是我们的程序问题,需要我们修改程序。

    • 体系结构:
  • Throwable:
  • Error:
  • Exception:
  • 非RuntimeException:编译时期异常
  • RuntimeException:运行时期异常

  • 异常演示:

  • 除数不能为0
package com.edu_01;
/**
 * 异常演示:
 * 除数不能为0 
 * 
 * java.lang.ArithmeticException: / by zero
 *      
 * 当我们的程序出现异常的时候我们的jvm虚拟机会给一个默认的处理方式:
 * 1.从出现异常的地方将程序停止掉
 * 2.将出现的异常类名,异常的原因,还有出现异常的位置全部打印到控制台
 * 
 * 你觉得jvm虚拟机给出的这种默认的处理方式好吗?
 * 答:不好,因为我们的程序是由多个部分组成,一旦一个部分出现了异长,
 * 我们不应该让 程序直接停止掉,应该让程序的其他模块继续正常运行,而针对这一个出现的异长给出一个
 * 具体的处理方案,这个处理方案最好不要影响到其他模块的程序执行
 *
 */
public class ExceptionDemo2 {
    public static void main(String[] args) {
        System.out.println("start");
        int a = 10;
        int b = 0;
        System.out.println(a/b);//java.lang.ArithmeticException: / by zero
        System.out.println("end");
    }

}
  • java.lang.ArithmeticException: / by zero

    • 针对异常,JVM默认的处理方案:
  • 一旦遇到程序出现了问题,就会把问题的类名,错误原因,错误的位置等信息打印在控制台,以便我们观察。
  • 并且,会自动从当前出问题的地方停止掉。

    • 这种处理方案虽然可以,但是不够好。
  • 哪里不好呢?
  • 其实程序出问题,不应该直接停止,因为我们的程序可能是由多部分组成的,
  • 其中一个部分出问题了,不应该影响其他部分的执行。
  • 所以,我们应该想办法让其他的部分能够执行下去。

    1.2

  • 我们是如何处理异常,保证各个部分不影响的呢?

  • 两种方案:
  • A:try…catch…finally
  • B:throws

    • try…catch…finally:
  • try{
  • 可能出现异常的代码
  • }catch(异常类名 变量名) {
  • 针对异常的代码处理
  • }finally {
  • 释放资源的地方
  • }

    • 我们简化一下第一个:
  • try{
  • 可能出现异常的代码
  • }catch(异常类名 变量名) {
  • 针对异常的代码处理
  • }
    代码演示:
package com.edu_01;
/**
 *  * 我们是如何处理异常,保证各个部分不影响的呢?
 * 两种方案:
 *      A:try...catch...finally
 *      B:throws
 * 
 * try...catch...finally:
 *      try{
 *          可能出现异常的代码
 *      }catch(异常类名 变量名) {
 *          针对异常的代码处理
 *      }finally {
 *          释放资源的地方
 *      }
 * 
 * 我们简化一下第一个:
 * try{
 *      可能出现异常的代码
 *  }catch(异常类名 变量名) {
 *      针对异常的代码处理
 *  }
 *
 */
public class ExceptionDemo3 {
    public static void main(String[] args) {
        System.out.println("start");
        int a= 10;
        int b = 0;
        try{
            //可能出现异常的代码
            System.out.println(a/b);//当除数为0的时候会抛出ArithmeticException这个异常
                                    //接着程序会拿着这个异常和catch里面的异常类已经对比                   
        }catch(ArithmeticException e){
            //当程序抛出ArithmeticException这个异常之后给出的具体的处理方法
            System.out.println("你的除数不能为0");
        }
        System.out.println("end");
    }

}

1.3
* 多个异常的处理(演示数组索引越界异常,除数为0异常)
* A:针对每一个出现问题的地方写一个try…catch语句
* B:针对多个异常,采用一个try,多个catch的情况。
* try…catch…catch…
*
* 遇到try里面的问题,就自动和catch里面进行匹配。
* 一旦匹配就执行catch里面的内容,执行完毕后,接着执行后面的代码。
*
* 注意:
* 如果异常间有子父关系,父必须在最后。
* 代码演示:

package com.edu_02;

import java.io.FileNotFoundException;

public class Animal {

    public void method() throws FileNotFoundException{}

    public void function(){}

}
package com.edu_02;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class Cat extends Animal{
    //重写父类的method()方法
    //A:子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。(父亲坏了,儿子不能比父亲更坏)
    public void method() throws FileNotFoundException{}

    //C:如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws
    //重写父类的function方法
    public void function(){
        //因为父类中没有任何异常抛出,子类重写的方法中如果有异常,只能抓不能抛
        try{
            FileInputStream fis = new FileInputStream("D://a.txt");
        }catch(FileNotFoundException e){
            System.out.println("文件未找到");
        }
    }


}
package com.edu_02;
/**
 *  1.9.1
 * 注意:
 *      A:子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。(父亲坏了,儿子不能比父亲更坏)
 *      B:如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常
        C:如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws

        上述仅仅针对编译时期异常
        与运行时期异常无关。
 *
 */
public class ExceptionDemo {

}

1.4
* 编译时期异常和运行时期异常的区别:
* 编译时期异常:Java程序必须显示处理,否则程序就会发生错误,无法通过编译
* FileNotFoundException(文件未找到异常)
* 运行时期异常:无需显示处理,也可以和编译时异常一样处理
* ArithmeticException

package com.edu_01;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

/**
 *  1.4
 * 编译时期异常和运行时期异常的区别:
 * 编译时期异常:Java程序必须显示处理,否则程序就会发生错误,无法通过编译
 *      FileNotFoundException(文件未找到异常)
 * 运行时期异常:无需显示处理,也可以和编译时异常一样处理
 *      ArithmeticException
 */
public class ExceptionDemo5 {
    public static void main(String[] args) {
        // * 运行时期异常:无需显示处理,也可以和编译时异常一样处理
        //   什么是异常的显示处理:try...catch...
        //      ArithmeticException
        try{
            System.out.println(10/0);
        }catch(ArithmeticException e){
            System.out.println("除数为0");
        }

        /**
         * 编译时期异常:Java程序必须显示处理,否则程序就会发生错误,无法通过编译
         * FileNotFoundException(文件未找到异常)
         */
        //此时就会出现一个编译时期的异常,此时程序的异常必须显示处理
        try{
            FileInputStream fis = new FileInputStream("D://a.txt");
        }catch(FileNotFoundException e){
            System.out.println("文件没找到");
        }

    }

}

1.5
* Throwable中的方法:(演示除数为0异常)
* printStackTrace():打印异常信息,程序从出问题的地方开始就会打印创建一个该异常对应的对象,
该对象直接调用打印方法

1.6(演示编译器异常,运行期异常)
* try…catch 是直接进行了处理。
* 而throws则是把异常处理的事情交给了调用者。
*
* throws用在方法上,声明方法有异常,交给调用者处理。
* 但是呢,如果是编译时期异常,调用就必须处理。
* 如果是运行时期异常,调用者可以处理,也可以不处理。

1.7
* throws:(演示文件未找到异常,除数为0异常)
* 用在方法声明后面,跟的是异常类名
* 可以跟多个异常类名,用,号隔开
* 表示抛出异常,由该方法的调用者来处理
* throws表示出现异常的一种可能,并不一定会发生这些异常
代码演示:

package com.edu_01;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

/**
 *  1.7
 * throws:(演示文件未找到异常,除数为0异常)
 *      用在方法声明后面,跟的是异常类名
 *      可以跟多个异常类名,用,号隔开
 *      表示抛出异常,由该方法的调用者来处理
 *      throws表示出现异常的一种可能,并不一定会发生这些异常
 */
public class ExceptionDemo7 {
    public static void main(String[] args){
        method();
        //method2();//将这个异常交给了调用者去进行处理
                 //1.可以继续往上throws,将异常继续向上进行抛出了
                 //2.自己try..catch...,相当与自己处理了这个异常
        try{
            method2();
        }catch(FileNotFoundException e){
            System.out.println("文件未找到");
        }
        /**
         * 我们以后遇到异常是抛还是抓呢?
         * 答:原则上能抛就抛,等到已经抛到了程序最底层的时候,最好就不要抛了,自己抓取。
         */

    }

    private static void method2() throws FileNotFoundException {
        //此时会抛出一个编译时期的异常,
        //我们必须在方法上进行声明,如果不声明的话,会一直编译报错
        FileInputStream fis = new FileInputStream("D://a.txt");
    }

    private static void method() throws ArithmeticException {
        //在方法声明上声明这个方法可能出现的异常,不代表这个异常一定会出现
        //此时仅仅是告诉我的调用者我的这个方法可能会出现异常,并不做具体的处理,交给
        //调用者自己去处理这个异常
        //此时抛出的 出数为0的异常,属于运行时期异常
        System.out.println(10/5);
    }

}

1.8
* 异常处理:
* try…catch…finally
*
* finally:一般用于释放资源。在数据库操作或者IO流比较常见。
*
* 特点:
* 被finally控制的语句体一定会执行
*
* 特殊情况:在执行到finally之前jvm退出了(比如System.exit(0))

package com.edu_01;
/**
 *  1.8
 * 异常处理:
 * try...catch...finally
 * 
 * finally:一般用于释放资源。在数据库操作或者IO流比较常见。
 * 
 * 特点:
 *      被finally控制的语句体一定会执行
 * 
 *      特殊情况:在执行到finally之前jvm退出了(比如System.exit(0))
 *
 */
public class ExceptionDemo8 {
    public static void main(String[] args) {
        try{
            System.out.println(10/0);
        }catch(ArithmeticException e){
            System.out.println("除数为0了");
            //在执行finally语句体之前jvm虚拟机退出了,那么就不会被执行
            System.exit(0);
        }finally{
            //这个代码块里面的代码一定会被执行的
            System.out.println("我是finally我一定会被执行");
        }

    }

}

1.9
* finally相关的面试题:
* final,finally的区别?
* final:最终的意思。可以修饰类,方法,变量。
* 修饰类,类不能被继承
* 修饰方法,方法不能被重写
* 修饰变量,变量是常量
* finally:
* 异常处理的一部分。被finally控制的代码一定会执行。
* 特殊情况:在执行到finally之前,jvm退出了。

1.9.1
* 注意:
* A:子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。(父亲坏了,儿子不能比父亲更坏)
* B:如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常
C:如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws

    上述仅仅针对编译时期异常
    与运行时期异常无关。

1.9.2
throw和throws的区别?
* throws:
* 用在方法声明后面,跟的是异常类名
* 可以跟多个异常类名,用逗号隔开
* 表示抛出异常,由该方法的调用者来处理
* throws表示出现异常的一种可能性,并不一定会发生这些异常
*
* throw:
* 用在方法体内,跟的是异常对象名
* 只能抛出一个异常对象名
* 表示抛出异常,由方法体内的语句处理
* throw则是抛出了异常,执行throw则一定抛出了某种异常?

案例演示:演示编译时期异常(文件未找到异常)和运行时期异常(除数为0异常)使用上的区别
* throw:
* 如果throw的是编译时期异常,在方法声明上必须用throws进行标记
* 如果throw的是运行时期异常,在方法声明上可以用throws进行标记,也可以不用。
代码演示:

package com.edu_03;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

/**
 *  throw和throws的区别?
 * throws:
 *      用在方法声明后面,跟的是异常类名
 *      可以跟多个异常类名,用逗号隔开
 *      表示抛出异常,由该方法的调用者来处理
 *      throws表示出现异常的一种可能性,并不一定会发生这些异常
 * 
 * throw:
 *      用在方法体内,跟的是异常对象名
 *      只能抛出一个异常对象名
 *      表示抛出异常,由方法体内的语句处理
 *      throw则是抛出了异常,执行throw则一定抛出了某种异常? 
 *
 */
public class ThrowDemo {
    public static void main(String[] args) {
        method();
        try {
            method2();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    private static void method2() throws FileNotFoundException{
        try{
            FileInputStream fis = new FileInputStream("D://a.txt");
        }catch(FileNotFoundException e){
            //当遇见这个异常之后,直接抛出(这就是我给出的处理方法)
            //如果【抛出的是编译时期异常的话,必须在方法声明上给予声明
            throw new FileNotFoundException();
        }

    }

    private static void method() throws ArithmeticException{
        int a = 10;
        int b = 2;
        if (b==0) {
            //在这里抛出的是运行时期异常,抛出这个异常的同时,可以在方法声明上给予声明,也可以不声明
            throw new ArithmeticException();
        }else {
            System.out.println(a/b);
        }
    }
}

一:File
1.1
File:文件和目录(文件夹)路径名的抽象表示形式。

1.2
File的构造方法:
File(String pathname):把一个路径名称封装成File对象
File(String parent, String child):把一个父路径和一个子路径封装成一个File对象
File(File parent, String child):把一个父路径File对象和一个子路径封装成一个File对象

代码演示:

package com.edu_01;

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

/**
  1.1
  File:文件和目录(文件夹)路径名的抽象表示形式。 

  1.2
  File的构造方法:
        File(String pathname):把一个路径名称封装成File对象
        File(String parent, String child):把一个父路径和一个子路径封装成一个File对象
        File(File parent, String child):把一个父路径File对象和一个子路径封装成一个File对象
 *
 */
public class FileDemo {
    public static void main(String[] args) throws IOException {
        //File(String pathname):把一个路径名称封装成File对象
        File file = new File("D://a.txt");
        System.out.println(file.createNewFile());//当文件不存在的时候,创建文件,如果文件存在,不创建

        System.out.println("------------");
        //File(String parent, String child):把一个父路径和一个子路径封装成一个File对象
        //File file = new File("D://test", "a.txt");
        //java.io.IOException: 系统找不到指定的路径,
        //创建文件的时候一定要保证路径存在
        //System.out.println(file.createNewFile());

        System.out.println("-----------------");
        //File(File parent, String child):把一个父路径File对象和一个子路径封装成一个File对象
//      File file = new File("D://test");
//      File file2 = new File(file, "a.txt");
//      System.out.println(file2.createNewFile());
//      
    }

}

1.3
创建功能:
A:创建文件
public boolean createNewFile():如果文件不存在,就创建。否则,不创建。
需求:D盘下造一个文件a.txt
B:创建目录
public boolean mkdir():如果目录不存在,就创建。否则,不创建。
需求:D盘下造一个文件夹test
public boolean mkdirs():如果目录不存在,就创建。否则,不创建。
即时父目录不存在,也可以连父目录一起创建。
需求:D盘下造一个文件夹(D:/aaa/bbb/ccc)
需求:D盘下造一个文件夹(“D:\ddd\eee\f.txt”);

注意事项:
A:你要造什么东西,就应该用对应的方法。
代码演示:

package com.edu_02;

import java.io.File;

/**
 *   1.3
   创建功能:
        A:创建文件
            public boolean createNewFile():如果文件不存在,就创建。否则,不创建。
            需求:D盘下造一个文件a.txt
        B:创建目录
            public boolean mkdir():如果目录不存在,就创建。否则,不创建。
            需求:D盘下造一个文件夹test
            public boolean mkdirs():如果目录不存在,就创建。否则,不创建。
                                    即时父目录不存在,也可以连父目录一起创建。
            需求:D盘下造一个文件夹(D:/aaa/bbb/ccc)
            需求:D盘下造一个文件夹("D:\\ddd\\eee\\f.txt");

   注意事项:
        A:你要造什么东西,就应该用对应的方法。
 *
 */
public class FileDemo {
    public static void main(String[] args) {
        //public boolean mkdir():如果目录不存在,就创建。否则,不创建。
        //需求:D盘下造一个文件夹test
        //File file = new File("D://test");
        //System.out.println(file.mkdir());

        System.out.println("----------");
        //public boolean mkdirs():如果目录不存在,就创建。否则,不创建。
        //即时父目录不存在,也可以连父目录一起创建。
        //File file = new File("D://aa//bb//a.txt");
        //System.out.println(file.mkdirs());


    }

}

1.4
删除功能:
public boolean delete():既可以删除文件,又可以删除目录。

路径问题:
A:绝对路径 就是以盘符开始的路径(d:\test\aaa\b.txt)
B:相对路径 就是不以盘符开始的路径(a.txt)
一般都是相对应当前的项目而言的。

注意事项:
A:Java程序的删除不走回收站。
B:如果目录内还有内容就不能删除。
代码演示:

package com.edu_02;

import java.io.File;

/**
 *   1.4
  删除功能:
        public boolean delete():既可以删除文件,又可以删除目录。

  路径问题:
        A:绝对路径  就是以盘符开始的路径(d:\\test\\aaa\\b.txt)
        B:相对路径  就是不以盘符开始的路径(a.txt)
                    一般都是相对应当前的项目而言的。

  注意事项:
        A:Java程序的删除不走回收站。
        B:如果目录内还有内容就不能删除。

 *
 */
public class FileDemo2 {
    public static void main(String[] args) {
        //删除D://a.txt
        //File file = new File("D://a.txt");
        //System.out.println(file.delete());


        //删除D://test//a.txt
        //File file = new File("D://test//a.txt");
        //System.out.println(file.delete());

        //删除D://test,删除文件夹的时候只能删除空的文件夹
        File file = new File("D://test");
        System.out.println(file.delete());

    }

}

1.5
判断功能
public boolean isDirectory():是否是目录
public boolean isFile():是否是文件
public boolean exists():是否存在
public boolean canRead():是否可读
public boolean canWrite():是否可写
public boolean isHidden():是否隐藏
代码演示:

package com.edu_02;

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

/**
 *    1.5
  判断功能
  public boolean isDirectory():是否是目录
  public boolean isFile():是否是文件
  public boolean exists():是否存在
  public boolean canRead():是否可读
  public boolean canWrite():是否可写
  public boolean isHidden():是否隐藏
 */
public class FileDemo3 {
    public static void main(String[] args) throws IOException {
        //在D://a.txt
        File file = new File("D://a.txt");
        //System.out.println(file.createNewFile());
        System.out.println("是否是目录:"+file.isDirectory());
        System.out.println("是否是文件:"+file.isFile());
        System.out.println("是否存在:"+file.exists());
        System.out.println("是否可读:"+file.canRead());
        System.out.println("是否可写:"+file.canWrite());
        System.out.println("是否隐藏:"+file.isHidden());

    }
}

1.6获取功能
public String getAbsolutePath():获取绝对路径
public String getPath():获取相对路径
public String getName():获取名称
代码演示:

package com.edu_02;

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

/**
 *1.6获取功能
  public String getAbsolutePath():获取绝对路径
  public String getPath():获取相对路径
  public String getName():获取名称
 *
 */
public class FileDemo4 {
    public static void main(String[] args) throws IOException {
        //创建一个文件
        File file = new File("a.txt");
        //创建一个文件
        //System.out.println(file.createNewFile());

        //  public String getAbsolutePath():获取绝对路径
        System.out.println(file.getAbsolutePath());//D:\workspace\十二天_File\a.txt

        //public String getPath():获取相对路径
        System.out.println(file.getPath());//a.txt

        //public String getName():获取名称
        System.out.println(file.getName());
    }

}

二:字节流及字节高效流
2.1 I/O流的分类(画图讲解)
插图演示:
io流的操作过程
* 有什么不懂得地方查看api
* IO流分类:
* 流向:
* 输入流
* 输出流
* 数据类型:
* 字节流
* 字节输入流
* 字节输出流
* 字符流
* 字符输入流
* 字符输出流
*
* 注意:一般我们在讨论IO的分类时,默认是按照数据类型分的。
*
* 字节流:
* 字节输入流 InputStream(抽象类)
* 字节输出流 OutputStream(抽象类)
* 字符流:
* 字符输入流 Reader
* 字符输出流 Writer
*
* 学习习惯:
* 字节流
* 字符流
*

2.2
* 需求:请用字节流往一个文本文件中写一句话:”helloworld”。
* 分析:
* 首先要知道是字节流
* 写数据我们就应该知道是字节输出流
* 所以最终选择了OutputStream
* 而OutputStream是抽象类,所以我们应该找其子类
* 文件这个单词是File,所以我们就大胆的猜测下:FileOutputStream存在否。
*
* 我们如何往一个文件写数据呢?
* 或者说就是字节输出流的操作步骤是什么呢?
* A:创建字节输出流对象
* B:调用写数据的方法
* C:释放资源
代码演示:

package cokm.edu_01;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 *  2.2
 * 需求:请用字节流往一个文本文件中写一句话:"helloworld"。
 * 分析:
 *      首先要知道是字节流
 *      写数据我们就应该知道是字节输出流
 *      所以最终选择了OutputStream
 *      而OutputStream是抽象类,所以我们应该找其子类
 *      文件这个单词是File,所以我们就大胆的猜测下:FileOutputStream存在否。
 * 
 * 我们如何往一个文件写数据呢?
 * 或者说就是字节输出流的操作步骤是什么呢?
 * A:创建字节输出流对象
 * B:调用写数据的方法
 * C:释放资源
 *
 */
public class OutputStreamDemo {
    public static void main(String[] args) throws IOException {
        /**
         * 怎么使用文件输出流往文件中途写数据?
         * 1.创建文件输出流对象
         * 2.调用输出流对象的方法给文件中写数据
         * 3.释放资源
         */
        //public FileOutputStream(String name)
        //public FileOutputStream(File file)
        //创建文件输出流对象
        FileOutputStream fos = new FileOutputStream("a.txt");

        //public FileOutputStream(File file)
        //File file = new File("a.txt");
        //FileOutputStream fos = new FileOutputStream(file);

        /**
         * FileOutputStream fos = new FileOutputStream("a.txt");
         * 做了那些事情?
         * 1.创建fos对象指向文件a.txt
         * 2.创建一个文件a.txt 
         */

        //调用输出流的写数据的方法给文件中写数据
        //public void write(byte[] b)
        byte[] byf = "helloworld".getBytes();
        fos.write(byf);

        //释放资源,关流操作
        fos.close();

        //关流之后,我们还能继续往文件中写数据码
        //这样是不行的。。
        //fos.write("java".getBytes());//java.io.IOException: Stream Closed

    }

}

做法:
A: 两个构造的区别?
FileOutputStream(File file)
FileOutputStream(String name)
FileOutputStream fos = new FileOutputStream(“fos.txt”);
请问上面这个操作做了哪几件事情?
* 1.创建了一个文件输出流fos,指向文件a.txt
* 2.创建了a.txt这个文件

B: fos.write(“helloworld”.getBytes());

C: fos.close();关流

D: fos.write(“java”.getBytes());

2.3
FileOutputStream写数据的方法
write(byte[] b)
write(int b) :一次写一个字节
write(byte[] b, int off, int len) :一次写一个字节数组的一部分

代码演示:

package cokm.edu_01;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 *  2.2
 * 需求:请用字节流往一个文本文件中写一句话:"helloworld"。
 * 分析:
 *      首先要知道是字节流
 *      写数据我们就应该知道是字节输出流
 *      所以最终选择了OutputStream
 *      而OutputStream是抽象类,所以我们应该找其子类
 *      文件这个单词是File,所以我们就大胆的猜测下:FileOutputStream存在否。
 * 
 * 我们如何往一个文件写数据呢?
 * 或者说就是字节输出流的操作步骤是什么呢?
 * A:创建字节输出流对象
 * B:调用写数据的方法
 * C:释放资源
 *
 */
public class OutputStreamDemo {
    public static void main(String[] args) throws IOException {
        /**
         * 怎么使用文件输出流往文件中途写数据?
         * 1.创建文件输出流对象
         * 2.调用输出流对象的方法给文件中写数据
         * 3.释放资源
         */
        //public FileOutputStream(String name)
        //public FileOutputStream(File file)
        //创建文件输出流对象
        FileOutputStream fos = new FileOutputStream("a.txt");

        //public FileOutputStream(File file)
        //File file = new File("a.txt");
        //FileOutputStream fos = new FileOutputStream(file);

        /**
         * FileOutputStream fos = new FileOutputStream("a.txt");
         * 做了那些事情?
         * 1.创建fos对象指向文件a.txt
         * 2.创建一个文件a.txt 
         */

        //调用输出流的写数据的方法给文件中写数据
        //public void write(byte[] b)
        byte[] byf = "helloworld".getBytes();
        fos.write(byf);

        //释放资源,关流操作
        fos.close();

        //关流之后,我们还能继续往文件中写数据码
        //这样是不行的。。
        //fos.write("java".getBytes());//java.io.IOException: Stream Closed

    }

}

2.4
字节输入流:
具体操作步骤:
* 字节输入流操作步骤:
* A:创建字节输入流对象
FileInputStream fis = new FileInputStream(“a.txt”);

  • B:调用方法读取数据
    一次读取一个字节:read() – 测试读取不到内容的时候的返回值(并且用循环改进)

  • C:释放资源
    fis.close

  • 练习:

  • A:把a.txt的内容复制到b.txt中
  • C:把d:\复制视频文件

  • 数据源:

  • IODemo.java – 读取数据 – InputStream – FileInputStream – 一次读取一个字节
  • 目的地:
  • Copy.java – 写出数据 – OutputStream – FileOutputStream – 一次写一个字节

2.5
字节输入流:
具体操作步骤:
* 字节输入流操作步骤:
* A:创建字节输入流对象
FileInputStream fis = new FileInputStream(“a.txt”);

  • B:调用方法读取数据(一次读取一个字节数组,提升效率)
    一次读取一个字节数组: public int read(byte[] b):返回实际读取长度,数据被读取到数组中。
    – 测试方法返回长度?根据String类的构造方法构造字符串
  • C:释放资源
    fis.close

(利用一次读写一个字节数组完成)
* 练习:
* A:把a.txt的内容复制到b.txt中
* C:把d:\复制视频文件
代码演示:

package cokm.edu_03;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyFile {
    public static void main(String[] args) throws IOException {
        //A:把a.txt的内容复制到b.txt中
        //封装数据源和目的地
        FileInputStream fis = new FileInputStream("OutputStreamDemo.java");
        FileOutputStream fos = new FileOutputStream("c.java");

        //2.读取数据源中的数据,将读取到的数据写入目的地中
        int by;
        while ((by=fis.read())!=-1) {
            //System.out.println(by);
            //将读取到的字节写入fos中
            fos.write(by);
        }

        //释放资源
        fos.close();
        fis.close();


    }

}

2.5
* 字节缓冲区流(也叫高效流):
* BufferedInputStream(read() 一次读取一个字节, public int read(byte[] b):返回实际读取长度,数据被读取到数组中。)
* BufferedOutputStream(write(byte[] b))
*
* 流
* 低级流: 基本的流,可以直接操作文件。
* 高级流:是操作基本流的流。

2.6
* 字节流复制文件(视频文件,并测试所用时间):
* A:基本字节流一次读写一个字节
* B:基本字节流一次读写一个字节数组
* C:高效字节流一次读写一个字节
* D:高效字节流一次读写一个字节数组

获取时间的方法:
System.currentTimeMillis()
代码演示:

package cokm.edu_06;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 *  2.6
 * 字节流复制文件(视频文件,并测试所用时间):
 * A:基本字节流一次读写一个字节      
 * B:基本字节流一次读写一个字节数组        
 * C:高效字节流一次读写一个字节      
 * D:高效字节流一次读写一个字节数组        

 获取时间的方法:
 System.currentTimeMillis()
 *
 */
public class Test {
    public static void main(String[] args) throws IOException {
        //复制文件开始之前的时间
        long startTime = System.currentTimeMillis();
//      method1();//A:基本字节流一次读写一个字节 15099
//      method2();// B:基本字节流一次读写一个字节数组  31(这种处理方案使用的是最多的)
//      method3();//C:高效字节流一次读写一个字节 234
        method4();//D:高效字节流一次读写一个字节数组16
        long endTime = System.currentTimeMillis();
        System.out.println(endTime-startTime);
    }

    private static void method4() throws IOException {
        // TODO Auto-generated method stub
        //C:高效字节流一次读写一个字节   
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D://b.mp4"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("a.mp4"));

        //高校字节流一次读写一个字节
        byte[] byf = new byte[1024];
        int len;
        while ((len = bis.read(byf))!=-1) {
            bos.write(byf, 0, len);
        }

        //3.关流
        bos.close();
        bis.close();
    }

    private static void method3() throws IOException {
        //C:高效字节流一次读写一个字节   
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D://b.mp4"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("a.mp4"));

        //高校字节流一次读写一个字节
        int by;
        while ((by = bis.read())!=-1) {
            bos.write(by);
        }

        //3.关流
        bos.close();
        bis.close();

    }

    private static void method2() throws IOException {
        // B:基本字节流一次读写一个字节数组    
        //疯转数据剧院和目的地
        FileInputStream fis = new FileInputStream("D://b.mp4");
        FileOutputStream fos = new FileOutputStream("a.mp4");

        //一次读写一个字节
        byte[] byf =new byte[1024];
        int len;
        while ((len=fis.read(byf))!=-1) {
            fos.write(byf, 0, len);
        }

        //3.释放资源
        fos.close();
        fis.close();
    }

    private static void method1() throws IOException {
        //A:基本字节流一次读写一个字节   
        //疯转数据剧院和目的地
        FileInputStream fis = new FileInputStream("D://b.mp4");
        FileOutputStream fos = new FileOutputStream("a.mp4");

        //一次读写一个字节
        int by;
        while ((by=fis.read())!=-1) {
            fos.write(by);
        }

        //3.释放资源
        fos.close();
        fis.close();
    }
}

三:编码问题

  • String中的编码和解码问题。

    • 编码:
  • 把我们能够看懂的字符转换为看不懂的数据
  • 解码:
  • 把我们看不懂的数据转换为看得懂的字符

    • 举例:
  • 电报/潜伏(余则成 深海)

    • 编码表:
  • 小本子,这个本子上记录了很多的汉字和对应的数据值。

    • 延安:
  • 今晚兴庆公园见

    • 发报员:
  • 今晚兴庆公园见
  • 转换成数据
  • 发送数据

    • 余则成:
  • 接收数据
  • 记录完毕后,就找出小本子,通过对应的数据值找到对应的字符
  • 今晚兴庆公园见

    public byte[] getBytes(String charsetName) 按照给定的编码方式,编码字节数组(gbk,utf-8)
    String(byte[] bytes, String charsetName) 按照给定的编码方式解码字符数组

    String s = "中国好";
    byte[] bytes = s.getBytes("utf-8");
    System.out.println(Arrays.toString(bytes));
    
    //String(byte[] bytes, String charsetName)
    System.out.println(new String(bytes,"gbk"));
    

    结论:用什么编码,就必须用什么解码。。
    代码演示:

package cokm.edu_07;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

/**
 * 编码:
 *      把你能看懂的东西,编码成你看不懂的数据
 * 解码:
 *      将你看不懂的数据,解码成你能够看懂的数据
 *
 *举例:谍战片。。。
 * 共产党地下组织:
 *      10  23 er tr -- 》去密码本(找到相应的解码) --- 》 今晚小树林见(明文) ---解码
 * 
 * 隐藏在国民党的特务:   
 *      今晚上小树林见(10  23 er tr)--  明文--》密文 -- 编码
 *
 * 目前我们使用的最多的两种编解码方式:gbk,utf-8 -- >理解为密码本
 *
 *
 *   public byte[] getBytes(String charsetName)  按照给定的编码方式,编码字节数组(gbk,utf-8)
     String(byte[] bytes, String charsetName) 按照给定的编码方式解码字符数组

            String s = "中国好";
            byte[] bytes = s.getBytes("utf-8");
            System.out.println(Arrays.toString(bytes));

            //String(byte[] bytes, String charsetName)
            System.out.println(new String(bytes,"gbk"));

         结论:用什么编码,就必须用什么解码。。
 *
 */
public class EncodingDemo {
    public static void main(String[] args) throws UnsupportedEncodingException {
        //创建一个字符串
        String s = "中国好";
        //byte[] byf = s.getBytes();
        //使用gbk去进行编码的时候,我们是将一个汉字编码成两个负数的字节。
        //当我们解码的时候,如果字节数组中遇见负数的话,会将前面和后面的负数进行拼接,去gbk码表中找到相应的明文
        //System.out.println(Arrays.toString(byf));

        System.out.println("=---------------");
        //byte[] bytes = s.getBytes("gbk");
        //System.out.println(Arrays.toString(bytes));

        System.out.println("------------");
        byte[] bytes = s.getBytes("utf-8");
        //当使用uft-8进行编码的时候,一个汉字会被编码成3个负数的字节
        //解码的时候,一旦遇见负数,三个拼接,去码表中进行解码
        System.out.println(Arrays.toString(bytes));

        System.out.println("--------------");
        System.out.println(new String(bytes));//涓浗濂?
        System.out.println(new String(bytes, "utf-8"));//中国好

        //结论:咱们以后使用哪种编码就使用哪种解码(编解码方式必须一致,不然会出现乱码)
        //我们以后编解码方式一般来说不需要指定特定的码表,一般来说使用默认的就可以

    }

}

四:字符流

一:字符流
Reader
Writer

1.1
* IO流中的编码和解码问题
* OutputStreamWriter:把字节输出流转换为字符输出流
* InputStreamReader:把字节输入流转换为字符输入流

1.2 转换流

 写入数据,把字节输出流转换为字符输出流(不指定码表)
 OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"));
 把字节输出流转换为字符输出流(指定码表)
 OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"), "GBK");
 OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"), "UTF-8"); 

 读取数据, 把字节输入流转换为字符输入流(不指定码表)
 InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"));
 把字节输入流转换为字符输入流(指定码表)
 InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"), "GBK");

总结:我们一般创建字符输入或者输出流一般情况下使用系统默认的码表就可以,
      如果来来回回需要指定码表的话,就显得非常的麻烦了

1.3 (将以上创建方式继续简化)
* 如果采用刚才的方式,创建对象写起来比较复杂。
* InputStreamReader isr = new InputStreamReader(new FileInputStream(“a.txt”));
* OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(“b.txt”));
* 为了简化这种操作,java就针对这两个转换的字符流提供其子类。
* FileReader
* FileWriter
* 它们的默认编码是采用系统编码。
构造学习:
FileWriter(File file)
FileWriter(String fileName)
FileReader(File file)
FileReader(String fileName)

 * flush()和close()的区别? 
 * A:flush  刷新缓冲区,流对象可以继续
 * B:close  先刷新缓冲区,再关闭流对象。流对象不可以继续使用了。

练习:给字符输出流里面利用方法写数据

 * 字符输出流操作步骤:
 * A:创建字符输出流对象
 * B:调用写数据方法
 * C:释放资源
 * 
 * 写数据方法:
 *      一次写一个字符  write(int c) 
 *      一次写一个字符数组write(char[] cbuf)
 *      一次写一个字符数组的一部分write(char[] cbuf, int off,int len)
 *      一次写一个字符串write(String str)
 *      一次写一个字符串的一部分write(String str,int off,int len)

代码演示:

package com.edu_02;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

/**
 * 1.3  (将以上创建方式继续简化)
     * 如果采用刚才的方式,创建对象写起来比较复杂。
     * InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));
     * OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt"));
     * 为了简化这种操作,java就针对这两个转换的字符流提供其子类。
     * FileReader
     * FileWriter
     * 它们的默认编码是采用系统编码。
     构造学习:
     FileWriter(File file) 
     FileWriter(String fileName) 
     FileReader(File file) 
     FileReader(String fileName)

     * flush()和close()的区别? 
     * A:flush  刷新缓冲区,流对象可以继续
     * B:close  先刷新缓冲区,再关闭流对象。流对象不可以继续使用了。

练习:给字符输出流里面利用方法写数据

     * 字符输出流操作步骤:
     * A:创建字符输出流对象
     * B:调用写数据方法
     * C:释放资源
     * 
     * 写数据方法:
     *      一次写一个字符  write(int c) 
     *      一次写一个字符数组write(char[] cbuf)
     *      一次写一个字符数组的一部分write(char[] cbuf, int off,int len)
     *      一次写一个字符串write(String str)
     *      一次写一个字符串的一部分write(String str,int off,int len)
 *
 */
public class FileWriterDemo {
    public static void main(String[] args) throws IOException {
        /**
         * 要给字符输出流中写数据步骤:
         * 1.创建字符输出流对象,并指向一个文件
         * 2.调用字符输出流写数据的方法给里面写数据
         * 3.刷新缓冲区
         * 4.关流
         */
        // FileWriter(File file) 
        // FileWriter(String fileName) 
        //1.创建字符输出流对象
        //FileWriter fw = new FileWriter(new File("c.txt"));
        FileWriter fw = new FileWriter("c.txt");

        //调用方法写数据
        //一次写一个字符  write(int c) 
        //fw.write('a');

        //一次写一个字符数组write(char[] cbuf)
        //char[] chs = {'h','e','l','l','o'};
        //fw.write(chs);


        //一次写一个字符数组的一部分write(char[] cbuf, int off,int len)
        //char[] chs = {'h','e','l','l','o'};
        //fw.write(chs, 2, 3);

        //一次写一个字符串write(String str)
        //fw.write("helloworld");


        //一次写一个字符串的一部分write(String str,int off,int len)
        fw.write("helloworld", 5, 5);


        //刷新缓冲区
        fw.flush();

        //关流
        fw.close();

    }

}

1.4 字符输入流
* 字符输入流操作步骤:
* A:创建字符输入流对象
FileReader fr = new FileReader(“a.txt”);

 * B:读取数据并显示在控制台
 *      a:一次读取一个字符
   一次读取一个字符
     int ch;
     while ((ch = fr.read()) != -1) {
     System.out.print((char) ch);
     }

 *      b:一次读取一个字符数组
    char[] chs = new char[1024];
    int len;
    while ((len = fr.read(chs)) != -1) {
        System.out.print(new String(chs, 0, len));
    }

 * C:释放资源
    fr.close();

1.5练习
注意:字符流输入输出流复制的文件是有要求的,简单来说只要是记事本打开文件的内容你能够看得懂,
就可以用字符流来进行复制,否则不行

具体原因:像复制MP3或者一些视频文件的时候,如果他的字节个数不是偶数的话,就会造成文件的缺损,
因为一个字符等于两个字节

1.利用字符流复制java文件(两种方式,一次读写一个字符,一次读写一个字符数组)

代码演示:

package com.edu_04;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
 * 我们使用字符流复制文件的时候,是什么文件都可以复制吗??
 * 答:不是。使用字符流复制文件对文件是有一定的要求的。
 * 什么要求呢?凡是使用记事本打开你肉眼可以看懂的文件
 * 都可以使用字符流进行复制,如果看不懂就不可以使用。
 * 
 * 
 *  具体原因:像复制MP3或者一些视频文件的时候,如果他的字节个数不是偶数的话,就会造成文件的缺损,
    因为一个字符等于两个字节
 *
 */
public class CopyFile {
    public static void main(String[] args) throws IOException {
        /**
         * 1.封装数据源和目的地
         * 2.一次读写一个字符或者一次读写一个字符数组
         * 3.关流
         */
        //1.封装数据源和目的地
        FileReader fr = new FileReader("InputStreamReaderDemo.java");
        FileWriter fw = new FileWriter("d.java");

        //2.1一次读写一个字符
        /*int ch;
        while ((ch=fr.read())!=-1) {
            fw.write(ch);//一次写一个字符
            fw.flush();//每写一次刷新缓冲区
        }*/


        //2.2一次读写一个字符数组
        char[] chs = new char[1024];
        int len;
        while ((len=fr.read(chs))!=-1) {
            fw.write(chs, 0, len);
            fw.flush();
        }


        //3.关流
        fw.close();
        fr.close();

    }

}

1.6 高效流:(重要,必须掌握。。)
需求:
* 需求:
* 给文件中写入十个”helloworld”,每写一个换一行,每写一行必须写入一个换行符“/r/n”
这样写的弊端,windows系统下的换行符是“/r/n”,Linux是”\n”,Mac是”\r”,这样会造成代码的通用性不强

 * BufferedReader:字符缓冲输入流
 构造:BufferedReader(Reader in) 
 特殊方法:public String readLine():包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null 

 * BufferedWriter:字符缓冲输出流
 构造:BufferedWriter(Writer out) 
 特殊方法:public void newLine():会根据系统来确定写入不同的换行符

最终练习:
* 复制文本文件:
* 4种
*
* 基本字符流一次读写一个字符
* 基本字符流一次读写一个字符数组
* 高效字符流一次读写一个字符
* 高效字符流一次读写一个字符数组
*
* 数据源:
* a.txt
* 目的地:
* b.txt
代码演示:

package com.edu_07;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
 * 最终练习:
 * 复制文本文件:
 *      4种
 * 
 *      基本字符流一次读写一个字符
 *      基本字符流一次读写一个字符数组
 *      高效字符流一次读写一个字符
 *      高效字符流一次读写一个字符数组
 * 
 * 数据源:
 *      a.txt
 * 目的地:
 *      j.txt
 *
 */
public class Test {
    public static void main(String[] args) throws IOException {
        method();//基本字符流一次读写一个字符
        method2();//基本字符流一次读写一个字符数组
        method3();//高效字符流一次读写一个字符
        method4();//高效字符流一次读写一个字符数组

    }

    private static void method4() throws IOException {
        //高效字符流一次读写一个字符数组
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("j.txt"));

        //一次读写一个字符数组
        char[] chs = new char[1024];
        int len;
        while ((len = br.read(chs))!=-1) {
            bw.write(chs, 0, len);
            bw.flush();
        }

        //释放资源
        bw.close();
        br.close();

    }

    private static void method3() throws IOException {
        //高效字符流一次读写一个字符
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("j.txt"));

        //一次读写一个字符
        int ch;
        while ((ch=br.read())!=-1) {
            bw.write(ch);
            bw.flush();
        }

        //关流
        bw.close();
        br.close();
    }

    private static void method2() throws IOException {
        //基本字符流一次读写一个字符数组
        FileReader fr = new FileReader("a.txt");
        FileWriter fw = new FileWriter("j.txt");

        //一次读写一个字节数组
        char[] chs = new char[1024];
        int len;
        while ((len = fr.read(chs))!=-1) {
            fw.write(chs, 0, len);
            fw.flush();
        }


        //关流
        fw.close();
        fr.close();

    }

    private static void method() throws IOException {
        //基本字符流一次读写一个字符
        FileReader fr = new FileReader("a.txt");
        FileWriter fw = new FileWriter("j.txt");

        //一次读取一个字符,返回的是该字符对应的int值
/*      System.out.println((char)fr.read());
        System.out.println((char)fr.read());
        System.out.println((char)fr.read());
        System.out.println((char)fr.read());
        System.out.println((char)fr.read());
        */

        int ch;
        while ((ch=fr.read())!=-1) {
            //System.out.println((char)ch);
            fw.write(ch);
            fw.flush();
        }

        //释放资源
        fr.close();
        fw.close();

    }

}

1.7
讲解(必须掌握,字符流中最常用的使用方式)
BufferedReader:字符缓冲输入流
BufferedWriter:字符缓冲输出流
的特性。

1.需求:向文件中写入十个中国好,每写一个换一行(普通方式实现,高效流输出流特性实现)
2.利用字符高效流的一次读写一行的特性复制文件
写数据注意三部曲:
bw.write(line);
bw.newLine();
bw.flush();
代码演示:

package com.edu_08;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriterDemo {
    public static void main(String[] args) throws IOException {
        //1.需求:向文件中写入十个中国好,每写一个换一行(高效流输出流特性实现)
        //创建高效字符输出流对象,并指向ff.txt文件
        BufferedWriter bw = new BufferedWriter(new FileWriter("ff.txt"));

        //写入数据
        for (int i = 0; i < 10; i++) {
            /**
             * 1.写一行
             * 2.换行
             * 3.刷新
             */
            bw.write("中国好");
            bw.newLine();
            bw.flush();
        }


        //释放资源
        bw.close();

    }

}

二:IO流练习
1.键盘录入数据并存储
* 键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低存入文本文件
*
* 分析:
* A:定义学生类
* B:创建集合,采用TreeSet集合,并按照比较器排序
* C:键盘录入5个学生信息并存入集合
* D:遍历集合,并把数据写到文本文件
代码演示:

package com.edu_09;

public class Student {
    private String name;
    private int chinese;
    private int math;
    private int english;
    public Student(String name, int chinese, int math, int english) {
        super();
        this.name = name;
        this.chinese = chinese;
        this.math = math;
        this.english = english;
    }
    public Student() {
        super();
        // TODO Auto-generated constructor stub
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getChinese() {
        return chinese;
    }
    public void setChinese(int chinese) {
        this.chinese = chinese;
    }
    public int getMath() {
        return math;
    }
    public void setMath(int math) {
        this.math = math;
    }
    public int getEnglish() {
        return english;
    }
    public void setEnglish(int english) {
        this.english = english;
    }

    //获取总成绩的方法
    public int getAllScore(){
        return chinese+math+english;
    }


}
package com.edu_09;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;

/**
 * 1.键盘录入数据并存储
 * 键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低存入文本文件
 * 
 * 分析:
 * 1.创建学生类
 * 2.键盘录入5个学生信息,并封装成学生对象,存储到TreeSet(使用比较器写一个排序算法)
 * 3.遍历集合,将信息存储到文本文件中(BufferedWriter)
 */
public class StudentTest {
    public static void main(String[] args) throws IOException {
        //创建一个TreeSet集合,并写一个比较器
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                int num = s1.getAllScore() - s2.getAllScore();
                int num2 = num==0?s1.getName().compareTo(s2.getName()):num;
                return num2;
            }
        });

        //键盘录入5个学生信息
        for (int i = 0; i < 5; i++) {
            //创建键盘录入对象
            Scanner sc = new Scanner(System.in);
            //接受键盘录入数据
            System.out.println("请输入你的姓名");
            String name = sc.nextLine();
            System.out.println("请输入你的语文成绩");
            int chinese = sc.nextInt();
            System.out.println("请输入你的数学成绩");
            int math = sc.nextInt();
            System.out.println("请输入你的英语成绩");
            int english = sc.nextInt();
            //封装成学生对象,存储集合
            Student s = new Student(name, chinese, math, english);
            ts.add(s);
        }
        System.out.println("数据录入完毕。。");
        //遍历集合,将集合中的数据全取不出来之后写入文件中,每一个学生信息占一行
        BufferedWriter bw = new BufferedWriter(new FileWriter("score.txt"));
        for (Student s : ts) {
            String info = s.getName()+"  "+s.getChinese()+"  "+s.getMath()+"  "+s.getEnglish()+"  "+s.getAllScore();
            //将拼接成的字符串写入文件中
            bw.write(info);
            bw.newLine();
            bw.flush();
        }

        //释放资源
        bw.close();

    }
}

三:设计模式(了解)
A:设计模式概述
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性以及代码的结构更加清晰.

B:设计模式分类
    创建型模式(创建对象的):   单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。
    行为型模式(对象的功能):   适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
    结构型模式(对象的组成):   模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、
    解释器模式、状态模式、策略模式、职责链模式、访问者模式。


    单例设计模式(掌握)
    A:单例设计思想
        保证类在内存中只有一个对象
    B:如何实现类在内存中只有一个对象呢?
        构造私有
        本身提供一个对象
        通过公共的方法让外界访问
    C:案例演示: 单例模式之饿汉式

    问题:面试中写哪种设计模式呢?

    工厂设计模式(掌握)
(简单工厂模式概述和使用)(理解)
A:简单工厂模式概述: 又叫静态工厂方法模式,它定义一个具体的工厂类负责创建一些类的实例
B:优点:   使用静态工厂模式的优点是实现责任的分割,该模式的核心是工厂类,工厂类含有必要的选择逻辑,可以决定什么时候创建哪一个产品的实例,
        而客户端则免去直接创建产品的责任,而仅仅是消费产品。也就是说静态工厂模式在不改变客户端代码的情况可以动态的增加产品。
        明确了类的职责
C:缺点
    这个静态工厂类负责所有对象的创建,如果有新的对象增加,或者某些对象的创建方式不同,
    就需要不断的修改工厂类,不利于后期的维护
D:案例演示

代码演示:

package com.edu_10;
/**
 *      单例设计模式(掌握)
        A:单例设计思想
            保证类在内存中只有一个对象
        B:如何实现类在内存中只有一个对象呢?
            构造私有
            本身提供一个对象
            通过公共的方法让外界访问
        C:案例演示:
        单例设计模式中:饿汉式
                                        懒汉式

        问题:面试中写哪种设计模式呢?
 *
 */
public class SingleInstanceDemo {
    /**
     * 饿汉式:当这个类一被加载,就在内存中创建了一个对象
     * 
     * 1.保证内存中只有一个对象(构造私有)
     * 2.在本类中创建一个该类的对象
     * 3.创建一个公共的访问方式给外界获取该对象
     */
    private SingleInstanceDemo(){}

    //静态的随着类的加载而加载
    private static SingleInstanceDemo instance = new SingleInstanceDemo();

    //给外界提供公共的访问方式,返回该对象
    public static SingleInstanceDemo getInstance(){
        return instance;
    }

}
package com.edu_10;

public class SingleInstanceDemo2 {
    /**
     * 单例设计模式之懒汉式:
     * 需要的时候才去创建对象,不需要的时候不创建
     */
    private SingleInstanceDemo2(){}

    private static SingleInstanceDemo2 instance = null;

    public static SingleInstanceDemo2 getInstance(){
        if (instance==null) {
            instance = new SingleInstanceDemo2();
        }
        return instance;
    }


}
package com.edu_10;

public class SingleInstanceDemo2Test {
    public static void main(String[] args) {
        SingleInstanceDemo2 instance = SingleInstanceDemo2.getInstance();
        SingleInstanceDemo2 instance2 = SingleInstanceDemo2.getInstance();
        System.out.println(instance==instance2);
    }

}
package com.edu_10;

public class SingleInstanceDemoTest {
    public static void main(String[] args) {
        SingleInstanceDemo instance = SingleInstanceDemo.getInstance();
        SingleInstanceDemo instance2 = SingleInstanceDemo.getInstance();
        System.out.println(instance==instance2);
    }

}
(抽象工厂模式的概述和使用)(理解)
A:工厂方法模式概述
    工厂方法模式中抽象工厂类负责定义创建对象的接口,具体对象的创建工作由继承抽象工厂的具体类实现。
B:优点
    客户端不需要在负责对象的创建,从而明确了各个类的职责,如果有新的对象增加,
    只需要增加一个具体的类和具体的工厂类即可,不影响已有的代码,后期维护容易,增强了系统的扩展性
C:缺点:   需要额外的编写代码,增加了工作量

代码演示:

package com.edu_11;

public class Test {
    public static void main(String[] args) {
//      Dog d = new Dog();
//      Dog d2 = new Dog();
//      d.eat();
//      d2.eat();
//      
//      Cat c = new Cat();
//      Cat c2 = new Cat();
//      c.eat();
//      c2.eat();


        //如果说我们的类和对象比较多的话,这样每次去new对象的话,就显得不是非常的方便了
        //此时我们需要专门创建一个工厂类,专门负责生产对象
        Animal a = AnimalFactory.getAnimal("dog");
        a.eat();
        a = AnimalFactory.getAnimal("cat");
        a.eat();

    }

}
package com.edu_11;

public abstract class Animal {
    public abstract void eat();

}
package com.edu_11;

public class AnimalFactory {
    //专门用来生产对象
    public static Animal getAnimal(String type){
        if ("dog".equals(type)) {
            return new Dog();
        }else if ("cat".equals(type)) {
            return new Cat();
        }
        return null;
    }
}
package com.edu_11;

public class Cat extends Animal{

    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

}
package com.edu_11;

public class Dog extends Animal{

    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }

}
  • 9
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值