IO流进阶

IO流进阶

一、缓冲流

1.1概述

  • 缓冲流也称为高效流、或者高级流。之前学习的字节流可以称为原始流。

  • 作用:缓冲流自带缓冲区(底层中自动创建了一个8K的字节数组)、可以提高原始字节流、字符流读写数据的性能。

1.2 分类

缓冲流分为四种

  • 字节缓冲输入流:BufferedInputStream
  • 字节缓冲输出流:BufferedOutputStream
  • 字符缓冲输入流:BufferedReader
  • 字符缓冲输出流:BufferedWriter

在这里插入图片描述

1.3 字节缓冲流

性能优化原理:

  • 字节缓冲输入流自带一个8KB缓冲池,以后我们直接从缓冲池读取数据(底层实现将内容读入到缓冲池),读数据性能较好。
  • 字节缓冲输出流自带一个8KB缓冲池,数据就直接写入到缓冲池中(底层实现将缓冲池的内容写入到目的地),写数据性能极高了。

在这里插入图片描述

字节缓冲流

  • 字节缓冲输入流:BufferedInputStream,提高字节输入流读数据的性能,读写功能(使用方法)上并无变化。
  • 字节缓冲输出流:BufferedOutputStream,提高字节输出流写数据的性能,读写功能(使用方法)上并无变化。

注意:**高级的缓冲流是用来包装低级的缓冲流,当需要追加文件内容时,需要在低级缓冲流上设置成追加,不是在高级缓冲流上设置;**当要使用缓冲流特有的方法时,需要使用子类去引用。

    //底层源码,可以看到到默认给了一个DEFAULT_BUFFER_SIZE,这是底层创建的字符数组(缓冲区),为8192大小
	public BufferedInputStream(InputStream in) {
        this(in, DEFAULT_BUFFER_SIZE);
    }
构造器说明
public BufferedInputStream(InputStream is)可以将低级的字节输入流包装成高级的缓冲字节输入流管道,从而提高字节输入流读数据的性能。
public BufferedOutputStream(OutputStream os)可以将低级的字节输出流包装成高级的缓冲字节输出流,从而提高字节输出流写数据的性能
        try (
                //低级的字节输入流
                InputStream is = new FileInputStream("D:\\练习目录\\原地址\\ideaIU-2021.1.1.exe");
                //包装成高级字节输出流
                InputStream bis = new BufferedInputStream(is);
                //低级的字节输出流
                OutputStream os = new FileOutputStream("D:\\练习目录\\目的地址\\ideaIU-2021.1.1.exe");
                //包装成高级的字节输出流
                BufferedOutputStream bos = new BufferedOutputStream(os);
        ) {
            int b;
            //这里读和写必须使用高级缓冲输入输出流
            while ((b = bis.read()) != -1)
                bos.write(b);

        } catch (Exception e) {
            e.printStackTrace();
        }

1.4 字节缓冲流的性能分析

建议使用字节缓冲输入流、字节缓冲输出流,结合字节数组的方式,目前来看是性能最优的组合。

分别使用不同的方式复制大视频观察性能情况

    public static void main(String[] args) {
        //这里我们拷贝一个700MB的文件
        lowInput();//一个字节读写 性能很差,读写慢
        lowInputArr();//3.608s  一个字节数组读写 性能很好,读写很快
        heigh();//7.867s 缓冲流一个字节读写 性能好,读写快
        heighArr();//0.842s 缓冲流一个数组读写 性能非常好 读写非常快

    }
    //高级的缓冲流一个数组读取
    public static void heighArr(){
        long start = System.currentTimeMillis();
        try(
                InputStream is = new FileInputStream("D:\\练习目录\\目的地址\\ideaIU-2021.1.1.exe");
                InputStream bis = new BufferedInputStream(is);
                OutputStream os = new FileOutputStream("D:\\练习目录\\目的地址\\4.exe");
                OutputStream bos = new BufferedOutputStream(os);
                ){
            //字节数组1024
            byte[] bArr = new byte[1024];
            while(bis.read(bArr)!=-1)
                bos.write(bArr);

        }catch (Exception e){
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("缓冲流一个数组读取:" + (end - start));
    }

    //高级的缓冲流一个字节读取
    public static void heigh(){
        long start = System.currentTimeMillis();
        try(
                InputStream is = new FileInputStream("D:\\练习目录\\目的地址\\ideaIU-2021.1.1.exe");
                //包装成缓冲输入流(这里采用父类引用指向子类对象 多态)
                InputStream bis = new BufferedInputStream(is);
                OutputStream os = new FileOutputStream("D:\\练习目录\\目的地址\\3.exe");
                //包装成高级的缓冲输出流
                OutputStream bos = new BufferedOutputStream(os);
                ){

            int b;
            while ((b = bis.read()) != -1)
                bos.write(b);

        }catch (Exception e){
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("缓冲流一个字节读取耗时:" + (end-start)/1000.0);
    }

    //低级一个字节数组输入输出
    public static void lowInputArr(){
        long start = System.currentTimeMillis();
        try(
                InputStream is = new FileInputStream("D:\\练习目录\\目的地址\\ideaIU-2021.1.1.exe");
                OutputStream os = new FileOutputStream("D:\\练习目录\\目的地址\\2.exe")
                ){

            byte[] bArr = new byte[1024];
            while (is.read(bArr) != -1)
                os.write(bArr);

        }catch (Exception e){
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("低级一个字节数组耗时:" + (end-start)/1000.0);
    }

    //一个字节输入输出
    public static void lowInput() {
        long start = System.currentTimeMillis();
        try (
                //字节输入输出流
                InputStream is = new FileInputStream("D:\\练习目录\\目的地址\\ideaIU-2021.1.1.exe");
                OutputStream os = new FileOutputStream("D:\\练习目录\\目的地址\\1.exe")

        ) {

            int b;
            while ((b = is.read()) != -1)
                os.write(b);
        } catch (Exception e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("低级一个字节读取耗时:" + (start - end / 1000.0));

    }

1.5 字符缓冲流

字符缓冲输入流:BufferedReader。

  • 作用:提高字符输入流读数据的性能,除此之外多了按照行读取数据的功能。(按行读时不会换行,需要我们自己写换行)

字符缓冲输出流:BufferedWriter。

  • 作用:提高字符输出流写数据性能,除此之外多了一个换行的功能。
输入构造器说明
public BufferedReader(Reader r)可以将低级的字符输入流包装成高级的缓冲字符输入流管道,从而提高字符输入流读数据的性能
新增方法说明
public String readLine()读取一行数据返回,如果没有可读的,就返回null
输出构造器说明
public BufferedWriter(Writer w)可以把低级的字符输出流包装成高级的缓冲字符输出流,从而提高字符输出流写数据的性能
新增方法说明
public void newLine()换行
        //读写文本文件的经典写法(常用写法)
        try(
                BufferedReader brd = new BufferedReader(new FileReader("TestModule\\src\\lzm\\Test1\\1.txt"));
                BufferedWriter bwt = new BufferedWriter(new FileWriter("TestModule\\src\\lzm\\Test1\\2.txt"))
                ){

            //读取一行临时存放的位置
            String line = "";
            while ((line = brd.readLine()) != null) {
                bwt.write(line);
                //换行
                bwt.newLine();
            }
        }catch (Exception e){
            e.printStackTrace();
        }

1.6 练习

使用字符缓冲流将以下内容按顺序恢复到一个新文件中

一、我是第一行
十一、我是第十一行
九、我是第九行
五、我是第五行
三、我是第三行
四、我是第四行
八、我是第八行
六、我是第六行
二、我是第二行
十、我是第十行
七、我是第七行

分析:

  • 定义一个缓存字符输入流管道与源文件接通
  • 定义一个List集合存储读取的每行数据
  • 定义一个循环按照行读取数据,存入到List集合中去
  • 对List集合中的每行数据按照首字符编号升序排序
  • 定义一个缓存字符输出管道与目标文件接通
  • 遍历List集合中的每个元素,用缓冲字符输出流管道写出并换行
    //将指定路径下的文本内容按照其序号排序
    public static void main(String[] args) {
        try(
                //一、创建字符输入流对象和字符输出流对象
                Reader rd = new FileReader("TestModule\\src\\lzm\\Test1\\练习.txt");
                Writer wt = new FileWriter("TestModule\\src\\lzm\\Test1\\1.txt");
                //包装成高级的缓冲输入输出流对象
                //此处如果想要使用子类的独特方法,就需要使用子类引用指向子类对象
                BufferedReader brd = new BufferedReader(rd);
                BufferedWriter bwt = new BufferedWriter(wt);
        ) {
            //二、创建集合存放文本中的每一行内容(按行存,所以用到读一行的方法)
            List<String> list = new ArrayList<>();
            //四、使用集合制定一个排序的规则(让list集合根据这个规则来排序)
            List<String> sortRule = new ArrayList<>();
            //五、将一二三...按顺序存放到规则集合中
            Collections.addAll(sortRule,"一","二","三","四","五","六","七","八","九","十","十一");
            String line = "";
            //三、每次读取一行放到集合中
            while ((line = brd.readLine()) != null) {
                list.add(line);
            }
            Collections.sort(list, new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    //六、根据规则排序
                    //思路:取出list集合中的每行第一个字符(因为这个字符是顺序),然后找出第一个字符在规则集合中的索引位置,然后根据两个索引位置就能比对出大小
                    //substring用来截取字符串某一段
                    //indexOf获取此时判断的第一个字符对象的索引值
                    return sortRule.indexOf(o1.substring(0,o1.indexOf("、"))) - sortRule.indexOf(o2.substring(0,o2.indexOf("、")));
                }
            });
            //七、遍历排序好的集合,将每一行写到指定文件中
            //记得换行
            for (String s : list) {
                bwt.write(s);
                bwt.newLine();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

二、转换流

2.1 乱码问题

什么时候会乱码?

  • 当读的文件和写的文件编码一致时不会乱码。
  • 当读内容的文件和写内容的文件编码格式不一致时,会导致乱码问题。

在这里插入图片描述

//使用相同编码读取不同编码的文件内容
        try(
                BufferedReader brd = new BufferedReader(new FileReader("TestModule\\src\\lzm\\Test1\\1.txt"));
        ) {
            //因为文件1.txt编码为gbk所以当你使用默认的utf编码读取时会乱码,所以写到utf文件时也会乱码
            System.out.println(brd.readLine());//һ�����ǵ�һ��
        } catch (Exception e) {
            e.printStackTrace();
        }

2.2 字符输入转换流

如何解决乱码问题呢?

  • 使用字符输入转换流
  • 可以提取文件(GBK)的原始字节流,字节流不会存在问题
  • 根据原始字节流以指定编码转换成字符输入流,这样字符输入流中的字符就不会乱码

字符输入转换流

  • InputStreamReader:可以将原始字节流按照指定编码转换成字符输入流

在这里插入图片描述

构造器说明
public InputStreamReader(InputStream is)可以把原始的字节流按照代码默认编码转换成字符输入流。几乎不用,与默认的FileReader一样。
public InputStreamReader(InputStream is,String charset)可以把原始的字节流按照指定编码转换成字符输入流,这样字符流中的字符就不乱码了。(重点)
		try(
                //创建字符输入转换流(将字节输入流转换为字符输入流)
                Reader isrd = new InputStreamReader(new FileInputStream("TestModule\\src\\lzm\\Test1\\1.txt"),"GBK");
                //将字符输入流包装成缓冲字符输入流
                BufferedReader brd = new BufferedReader(isrd)
        ){

            System.out.println(brd.readLine());//一、我是第一行
        }catch (Exception e){
            e.printStackTrace();
        }

2.3 字符输出转换流

如何控制写出去的字符编码,也就是按照指定编码写到文件中?

  • 可以把字符以指定编码获取字节后再使用字节输出流写出去
    • 例如:“我爱中国”.getBytes(编码格式)
  • 也可以使用字符输出转换流实现

字符输出转换流

  • OutputStreamWriter:可以将字节输出流按照指定编码转换成字符输出流,从而指定写出去的字符编码格式
构造器说明
public OutputStreamWriter(OutputStream os)可以把原始的字节输出流安札奥代码默认编码转换成字符输出流,几乎不用
public OutputStreamWriter(OutputStream os,String charset)可以把原始的字节输出流按照指定编码转换成字符输出流(重点)
        try(
                //将字节流包装成高级缓冲字节流,再将缓冲字节流转换成字符流
                Reader rdb = new InputStreamReader(new BufferedInputStream(new FileInputStream("TestModule\\src\\lzm\\Test1\\1.txt")),"GBK");
                Writer wtb = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream("TestModule\\src\\lzm\\Test1\\2.txt")),"utf-8");
                //将字符流包装成缓冲字符流
                BufferedReader brdb = new BufferedReader(rdb);
                BufferedWriter bwtb = new BufferedWriter(wtb);
                ){

            //此处因为1.txt是gbk编码,所以字节输入流指定编码然后转换成字符流
            //若输出的文件是utf-8编码,可将字节输出流指定编码然后转换为字符流,也可不指定,因为默认是utf-8
            String line = "";
            while ((line = brdb.readLine()) != null) {
                bwtb.write(line);
                bwtb.newLine();
            }

        }catch (Exception e){
            e.printStackTrace();
        }

三、序列化对象

3.1 对象序列化

作用:以内存为基准,把内存中的对象存储到磁盘文件中去,称为对象序列化。

注意:

  • 对象序列化必须实现序列化接口Serializable

在这里插入图片描述

使用的是对象字节输入流:ObjectOutputStream

构造器说明
public ObjectOutputStream(OutputStream out)把低级字节输出流包装成高级的对象字节输出流
方法名称说明
public final void writeObject(Object obj)把对象写出去到对象序列化流的文件夹中
//主方法
    public static void main(String[] args) {

        Student s = new Student("张三",15,"火星130号");

        try(
                //因为我们要使用特有的writeObject方法,所以不能用父类引用
                ObjectOutputStream oop = new ObjectOutputStream(new FileOutputStream("TestModule\\src\\lzm\\Test1\\obj.txt"))
                ){

            //括号中为对象
            oop.writeObject(s);

        }catch (Exception e){
            e.printStackTrace();
        }

    }

//对象类
//对象序列化需要实现序列化接口,该接口相当于提示JVM虚拟机,底层去实现对象序列化
public class Student implements Serializable {

    private String name;
    private int age ;
    private String site;

    public Student() {
    }

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

    public Student(String name, int age, String site) {
        this.name = name;
        this.age = age;
        this.site = site;
    }
    //此处省略getter和setter方法
}

3.2 对象反序列化

作用:以内存为基准,把存储到磁盘文件中的对象数据恢复到内存中的对象,称为对象反序列化。

使用的是对象字节输入流:ObjectInputStream

构造器说明
public ObjectInputStream(InputStream out)把低级字节输入流包装成高级的对象字节输入流
特有方法说明
public Object readObject()把存储到磁盘文件中的对象数据恢复到内存中的,返回值为对象
        try(
                //这里将刚刚序列化的对象文件地址变成反序列化的地址,将其恢复到内存
                ObjectInputStream ois = new ObjectInputStream(new FileInputStream("TestModule\\src\\lzm\\Test1\\obj.txt"))
                ){

            //此处因为我们直到文件中存放的对象是Student所以我们直接强制转换即可
            Student s = (Student) (ois.readObject());
            //因为重写了toString方法
            System.out.println(s);//Student{name='张三', age=15, site='火星130号'}

        }catch (Exception e){
            e.printStackTrace();
        }

3.3 注意事项

  • 对象如果要序列化,对象类必须实现Serializable接口
  • transient修饰的成员变量不参与序列化
  • 序列化的版本号与反序列化的版本号必须一致才不会报错(例子:当一个类的序列化版本号为1,然后序列化保存到了文件中,此时如果类中修改了一个字段,那么当你用反序列化将文件时,会报错java.io.InvalidClassException,此时需要重新序列化对象然后再反序列化)
    private static final long serialVersionUID = 1;

四、打印流

4.1 PrintStream、PrintWriter

作用:打印流可以实现方便、高效的打印数据到文件中去。打印流一般指:PrintStream,PrintWrite两个类。

可以实现打印什么数据就是什么数据,例如打印整数97就是97.

在这里插入图片描述

PrintStream和PrintWriter的区别?

  • 打印数据功能一模一样,都是使用方便,性能高效(优势)
  • PrintWriter继承自字符输出流Writer,支持写字符数据出去
  • PrintStream继承自字节输出流OutputStream,支持写字节数据的方法
PrintStream
构造器说明
public PrintStream(OutputStream os)打印流直接通向字节输出流管道
public PrintStream(File f)打印流直接通向文件对象
public PrintStream(String filepath)打印流直接通向文件路径
**public **void print(**任意类型 **)打印任意类型数据出去
PrintWriter
构造器说明
public PrintWriter(OutputStream os)打印流直接通向字节输出流管道
public PrintWriter(Writer w)打印流直接通向字符输出流管道
public PrintWriter(File f)打印流直接通向文件对象
public PrintWriter(String filepath)打印流直接通向文件路径
方法说明
public void print(任意类型)打印任意类型数据出去
        try(
                //创建打印流对象
//                PrintStream ps = new PrintStream("TestModule\\src\\lzm\\Test1\\1.txt");
                //打印流想要追加数据
                PrintStream ps = new PrintStream(new FileOutputStream("TestModule\\src\\lzm\\Test1\\1.txt",true))
                ) {
            //写什么打印什么
            ps.println(111);
            ps.println('a');
            ps.println("我写什么就打印什么");
        } catch (Exception e) {
            e.printStackTrace();
        }

4.2 输出语句的重定向

属于打印流的一种应用,可以把输出语句的打印位置改到文件中。

System.out.println中out就进行输出重定向将数据打印到控制台

//将输出语句的打印位置改为文件地址
PrintStream ps = new PrintStream("文件地址");
System.setOut(ps);
try (
                //指定输出流的文件
                PrintStream ps = new PrintStream(new FileOutputStream("TestModule\\src\\lzm\\Test1\\1.txt",true));
        ) {
            System.out.println("我打印控制台");
            System.out.println("我打印控制台");
            System.setOut(ps);
            System.out.println("我打印输出流文件中");
            System.out.println("我打印输出流文件中");
        } catch (Exception e) {
            e.printStackTrace();
        }

五、Properties

Properties属性集对象

  • 其实就是一个Map集合,但是我们一般不会当集合使用,因为HashMap更好用。

Properties的核心作用

  • Properties代表的是一个属性文件,可以把自己对象中的键值对信息存放到一个属性文件中去
  • 属性文件:后缀为.properties结尾的文件,里面的内容都是key=value,后续做系统配置信息用。

5.1 常用API

  • Properties和IO流结合使用
构造器说明
void load(InputStream inStream)从输入字节流读取属性列表(键和值对)
void load(Reader reader)从输入字符流读取属性列表(键和值对)
void store(OutputStream out,String comments)将此属性列表(键和值)写入此Properties表中,以适合于load(InputStream)方法的格式写入输入字节流
void store(Writer writer,Sting comments)将此属性列表(键和值)写入Properties表中,以适合使用load(Reader)方法的格式写入输出字符流
void Object setProperty(String key,String value)保存键值对(put)
public String getProperty(String key)使用此属性列表中指定的键搜索属性值(get)
public Set stringPropertyNames()所有键的名称的集合(keySet())
        Properties ppt = new Properties();
        try {
            //将Properties键值对保存到文件
//            ppt.store(new FileWriter("TestModule\\src\\lzm\\Test1\\1.txt"),"我是心得,可写可不写");
            //#\u6211\u662F\u5FC3\u5F97\uFF0C\u53EF\u5199\u53EF\u4E0D\u5199
            //#Fri Sep 30 08:45:14 CST 2022
            //李四=5201314
            //张三=123456
            //王五=666666
            //加载Properties键值对
            ppt.load(new FileReader("TestModule\\src\\lzm\\Test1\\1.txt"));
            //{李四=5201314, 张三=123456, 王五=666666}
            System.out.println(ppt);
        } catch (IOException e) {
            e.printStackTrace();
        }

六、IO框架

6.1 commons-io概述

  • commons-io是apache开元基金组织提供的一组有关IO操作的类库,可以提高IO功能开发的效率
  • commons-io工具包提供了很多有关io操作的类。有两个主要的类FileUtils,IOUtils
FiileUtils主要方法
String readFileToString(File file,String encoding)读取文件的数据,返回字符串,可以指定读时的字符编码
void copyFile(File srcFile,File destFile)复制文件(源文件对象,目的文件对象)
void copyDirectoryToDirectory(File srcDir,File destDir)复制文件夹(源文件夹对象,目的文件夹对象)

6.2 使用步骤

  • 在项目中创建一个文件夹:lib
  • 将commons-io-2.6.jar文件复制到lib文件夹
  • 在jar文件上右击—>Add as Library —>点击OK
  • 在类中导入包使用即可

在这里插入图片描述

        try{
            //复制文件
//            IOUtils.copy(new FileInputStream("D:\\练习目录\\原地址\\基础班\\9.20自习练习题1.docx"),
//                    new FileOutputStream("D:\\练习目录\\原地址\\9.20自习练习题2.docx"));
            //复制文件到指定文件夹下
//            FileUtils.copyFileToDirectory(new File("D:\\练习目录\\原地址\\基础班\\9.20自习练习题1.docx"),
//                    new File("D:\\练习目录\\原地址\\"));
            //复制文件夹(非空也能复制)
//            FileUtils.copyDirectoryToDirectory(new File("D:\\练习目录\\原地址"),new File("D:\\练习目录\\目的地址\\"));

            //删除文件夹(非空文件夹也能删除)
//            FileUtils.deleteDirectory(new File("D:\\练习目录\\目的地址"));

            //JDK新增功能
            Files.copy(Path.of("D:\\练习目录\\原地址\\基础班\\9.20自习练习题1.docx"),new FileOutputStream("D:\\练习目录\\原地址\\基础班\\9.20自习练习题2.docx"));

        }catch (Exception e){
            e.printStackTrace();
        }

七、练习

7.1 点名器

有一个文件里面存储了班级同学的姓名,每一个姓名占一行,要齐通过程序实现随机点名器

        //有一个文件里面存储了班级同学的姓名,每一个姓名占一行,要齐通过程序实现随机点名器
        try(
                //建立一个缓冲字符输入流管道与源文件接通
                BufferedReader brd = new BufferedReader(new FileReader("TestModule\\src\\lzm\\Test1\\1.txt"));
                ) {
            //line临时存储一行字符串
            String line = "";
            //创建一个List集合用来存放每一行的名字
            List<String> list = new ArrayList();
            //遍历并存放到集合中
            while ((line = brd.readLine()) != null){
                list.add(line);
            }
            //随机数生成,生成的最大值是集合元素的个数
            Random rd = new Random();
            int num = rd.nextInt(list.size());
            //打印集合的随机数位置的名称
            System.out.println(list.get(num));
        }catch (Exception e){
            e.printStackTrace();
        }

7.2 点名器升级版

有一个文件里面存储了班级同学的姓名,每一个姓名占一行,要求通过程序实现随机点名器。第三次必定是张三同学

        //有一个文件里面存储了班级同学的姓名,每一个姓名占一行,要求通过程序实现随机点名器。第三次必定是张三同学
        try(
                //建立一个缓冲字符输入流管道与源文件接通
                BufferedReader brd = new BufferedReader(new FileReader("TestModule\\src\\lzm\\Test1\\1.txt"));
                ) {
            //line临时存储一行字符串
            String line = "";
            //创建一个List集合用来存放每一行的名字
            List<String> list = new ArrayList();
            //遍历并存放到集合中
            while ((line = brd.readLine()) != null){
                list.add(line);
            }
            //随机数生成,生成的最大值是集合元素的个数
            Random rd = new Random();
            //计数,随机索引位置
            int count = 1,index;
            while(count<20){
                //当第三次点名时,就去寻找张三所在的索引位置并赋值给index
                if (count%3==0){
                    index = list.indexOf("张三");
                }else{
                    index = rd.nextInt(list.size());
                }
                //打印集合的随机数位置的名称
                System.out.println(list.get(index));
                count++;
            }
        }catch (Exception e){
            e.printStackTrace();
        }

7.3 登录案例

写一个登录小案例

  • 将正确的用户名和密码手动保存在本地userinfo.txt文件中。
  • 保存为:username=zhangsan&password=123
  • 让用户键盘录入用户名和密码
  • 比较用户录入的和正确的用户名密码是否一致
  • 如果一致则打印登陆成功
  • 如果不一致则打印登陆失败
        try (
                //建立一个缓冲字符输入流管道与源文件接通
                BufferedReader brd = new BufferedReader(new FileReader("TestModule\\src\\lzm\\Test1\\1.txt"));
        ) {
            //将文件中每一行用户名和密码存入集合中
            String line = "";
            List list = new ArrayList();
            while ((line = brd.readLine()) != null){
                list.add(line);
            }
            Scanner sc = new Scanner(System.in);
            System.out.print("用户名:");
            String username = sc.next();
            System.out.print("密码:");
            String password = sc.next();
            boolean flag = false;
            //在输入的用户名和密码中添加共同的标识(username=用户名&password=密码)
            String login = "username=" +username + "&password=" + password;
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).equals(login)) {
                    flag = true;
                    break;
                }
            }
            if (flag == false){
                System.out.println("登录失败");
            }else{
                System.out.println("登录成功");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

7.4 自动登录案例

①将正确的用户名和密码手动保存在本地的userinfo.txt文件中。

②保存格式为:username=zhangsan&password=123

③让用户键盘录入用户名和密码

④比较用户录入的和正确的用户名密码是否一致

⑤如果一致则打印登陆成功,并将用户录入的数据保存到本地cookie.txt文件中。

​ 保存格式为:username=zhangsan

​ password=123

⑤如果不一致则打印登陆失败

再次运行时,则从本地cookie.txt自动登录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值