java学习笔记8

字节数组拷贝之available()方法

  • A:案例演示
    • int read(byte[] b):一次读取一个字节数组
    • write(byte[] b):一次写出一个字节数组
    • available()获取读的文件所有的字节个数
  • 弊端:有可能会内存溢出
package com.heima.stream;

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

public class Demo3_Copy {

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        //第二种拷贝,不推荐使用,因为有可能会导致内存溢出
        FileInputStream fis = new FileInputStream("Math.jpg");
        FileOutputStream fos = new FileOutputStream("copy.jpg");
        
        byte[] arr = new byte[fis.available()];     //创建与文件大小一样的字节数组
        fis.read(arr);
        fos.write(arr);
        fis.close();
        fos.close();
    }

    public static void demo1() throws FileNotFoundException, IOException {
        FileInputStream fis = new FileInputStream("Math.jpg");  //创建输入流对象,关联Math.jpg
        FileOutputStream fos = new FileOutputStream("copy.jpg");    //创建输出流对象,关联copy.jpg
        
        int b;
        while((b = fis.read()) != -1) {     //在不断的读取每一个字节
            fos.write(b);                   //将每一个字节写出
        }
        
        fis.close();                        //关流释放资源
        fos.close();
    }

}

定义小数组及小数组的标准格式

  • write(byte[] b)
  • write(byte[] b, int off, int len)将指定byte数组中从偏移量off开始的len个字节写入此文件输出流
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo4_ArrayCopy {

    /**
     * 第三种拷贝
     * 定义小数组
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("xxx.txt");
        FileOutputStream fos = new FileOutputStream("yyy.txt");
        
        byte[] arr = new byte[2];   //一般情况下会设置为1024的整数倍
        int len;
        while((len = fis.read(arr)) != -1) {//如果忘记加arr,返回的就不是读取的字节个数,而是字节的码表值
            fos.write(arr,0,len);   //将arr数组中从偏移量0开始的len个字节写入此文件输出流
        }
    }

    public static void demo1() throws FileNotFoundException, IOException {
        FileInputStream fis = new FileInputStream("xxx.txt");   //文件内容为abc
        byte[] arr = new byte[2];
        int a = fis.read(arr);          //将文件上的字节读取到字节数组中,读的时候指针会移位,若没有数据则返回-1
        
        System.out.println(a);          //读到的有效字节个数
        for (byte b : arr) {            //第一次获取到文件上的a和b
            System.out.println(b);      //97,98
        }
        
        int c = fis.read(arr);
        System.out.println(c);
        for (byte b : arr) {
            System.out.println(b);      //99,98(这个98是数组上次存留下来的量)
        }
        fis.close();
    }

}

BufferedInputStream和BufferOutputStream拷贝

  • A:缓冲思想
    • 字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,
    • 这是加入了数组这样的缓冲区效果,java本身在设计的时候,
    • 也考虑到了这样的设计思想(装饰设计模式后面讲解),所以提供了字节缓冲区流
  • B.BufferedInputStream
    • BufferedInputStream内置了一个缓冲区(数组)
    • 从BufferedInputStream中读取一个字节时
    • BufferedInputStream会一次性从文件中读取8192个, 存在缓冲区中, 返回给程序一个
    • 程序再次读取时, 就不用找文件了, 直接从缓冲区中获取
    • 直到缓冲区中所有的都被使用过, 才重新从文件中读取8192个
  • C.BufferedOutputStream
    • BufferedOutputStream也内置了一个缓冲区(数组)
    • 程序向流中写出字节时, 不会直接写到文件, 先写到缓冲区中
    • 直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件
  • E.小数组的读写和带Buffered的读取哪个更快?
    • 定义小数组如果是8192个字节大小和Buffered比较的话
    • 定义小数组会略胜一筹,因为读和写操作的是同一个数组
    • 而Buffered操作的是两个数组
package com.heima.stream;

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

public class Demo5_BufferCopy {

    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("Math.jpg");  //创建输入流对象,关联Math.jpg
        FileOutputStream fos = new FileOutputStream("copy.jpg");//创建输出流对象,关联copy.jpg
        BufferedInputStream bis = new BufferedInputStream(fis); //创建缓冲区对象,对输入流进行包装让其变得更加强大
        BufferedOutputStream bos = new BufferedOutputStream(fos);//创建缓冲区对象,对输出流进行包装让其变得更加强大
        
        int b;
        while((b = bis.read()) != -1) {
            bos.write(b);
        }
        
        bis.close();
        bos.close();
    }

}
带缓冲区的拷贝.png

flush和close方法的区别

  • flush()方法
    • 用来刷新缓冲区的,刷新后可以再次写出
  • close()方法
    • 用来关闭流释放资源的的,如果是带缓冲区的流对象的close()方法,不但会关闭流,还会再关闭流之前刷新缓冲区,关闭后不能再写出
package com.heima.stream;

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

public class Demo5_BufferCopy {

   /**
    * close方法
    * 具备刷新的功能,在关闭流之前,就会先刷新一次缓冲区,将缓冲区的字节全部刷新到文件上,再关闭。关闭后不能再写
    * flush方法
    * 具备刷新的功能,刷新完之后还可以继续写。应用QQ聊天的小程序
    */
   public static void main(String[] args) throws IOException {
       //flush和close方法的区别
       BufferedInputStream bis = new BufferedInputStream(new FileInputStream("Math.jpg"));
       BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.jpg"));
       
       int b;
       while((b = bis.read()) != -1) {
           bos.write(b);
       }
       
       //bos.flush();
       bis.close();
       bos.close();
   }

   public static void demo1() throws FileNotFoundException, IOException {
       FileInputStream fis = new FileInputStream("Math.jpg");  //创建输入流对象,关联Math.jpg
       FileOutputStream fos = new FileOutputStream("copy.jpg");//创建输出流对象,关联copy.jpg
       BufferedInputStream bis = new BufferedInputStream(fis); //创建缓冲区对象,对输入流进行包装让其变得更加强大
       BufferedOutputStream bos = new BufferedOutputStream(fos);//创建缓冲区对象,对输出流进行包装让其变得更加强大
       
       int b;
       while((b = bis.read()) != -1) {
           bos.write(b);
       }
       
       bis.close();
       bos.close();
   }

}

字节流读写中文

  • 字节流读取中文的问题
    • 字节流在读中文的时候有可能会读到半个中文,造成乱码
  • 字节流写出中文的问题
    • 字节流直接操作的字节,所以写出中文必须将字符串转换成字节数组
    • 写出回车换行 write("\r\n".getBytes());
package com.heima.stream;

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

public class Demo6_Chinese {

    public static void main(String[] args) throws IOException {
        FileOutputStream fos  = new FileOutputStream("zzz.txt");
        fos.write("我读书少,你不要骗我".getBytes());
        //"我读书少,你不要骗我".getBytes()   转化为字节数组
        fos.write("\r\n".getBytes());
        fos.close();
    }

    public static void demo1() throws FileNotFoundException, IOException {
        FileInputStream fis = new FileInputStream("yyy.txt");
        byte[] arr = new byte[3];
        int len;
        while((len = fis.read(arr)) != -1) {
            System.out.println(new String(arr,0,len));  //输出中文,字节流读取中文再输出会出现乱码
        }
        //String(byte[] bytes, int offset, int length)通过使用平台的默认字符集解码指定的 byte 子数组,构造一个新的 String。
        fis.close();
    }

}

流的标准处理异常代码1.6版本及其以前和流的标准处理异常代码1.7版本

  • 原理
    • 在try()中创建的流对象必须实现了AutoCloseable这个接口,如果实现了,在try后面的{}(读写代码)执行后就会自动调用,流对象的close方法将流关掉(1.7)
package com.heima.stream;

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

public class Demo7_TryFinally {

    public static void main(String[] args) throws IOException {
        //1.7自动实现了自动关闭流,通过AutoCloseable实现
        try(
            FileInputStream fis = new FileInputStream("xxx.txt");   
            FileOutputStream fos = new FileOutputStream("yyy.txt");
            MyClose mc = new MyClose(); 
        ){
            int b;
            while((b = fis.read()) != -1) {
                fos.write(b);
            }
        }
    }

    public static void demo1() throws FileNotFoundException, IOException {
        //1.6以及以前
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("xxx.txt");   //有可能赋值失败,所以fis要在上面初始化
            fos = new FileOutputStream("yyy.txt");
            
            int b;
            while((b = fis.read()) != -1) {
                fos.write(b);
            }
        }finally {
            try{
                if(fis != null)
                    fis.close();    //null调用方法会出现空指针异常
            }finally{               //try finally的嵌套目的是能关一个尽量关一个
                if(fos != null)
                    fos.close();
            }   
        }
    }

}

class MyClose implements AutoCloseable {
    public void close() {
        System.out.println("我关了");
    }
    
}

图片加密

package com.heima.test;

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

public class Test1 {

    public static void main(String[] args) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("copy.jpg"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy2.jpg"));
        
        int b;
        while((b = bis.read()) != -1) {
            bos.write(b ^ 123); //加密,每个字节异或一个数。解密,每个字节再异或上同一个数
        }
        bis.close();
        bos.close();
    }

}

拷贝文件

在控制台录入文件的路径,将文件拷贝到当前项目下

package com.heima.test;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;

public class Test2 {

    /**
     * 在控制台录入文件的路径,将文件拷贝到当前项目下
     * 
     * 1,定义方法对键盘录入的路径进行判断,如果是文件就返回
     * 2,在主方法中接收该文件
     * 3,读和写该文件
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        File file = getFile();          //获取文件
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file.getName()));
        
        int b;
        while((b = bis.read()) != -1) {
            bos.write(b);
        }
        
        bis.close();
        bos.close();
    }
    /*
     * 定义一个方法获取键盘录入的文件路径,并封装成File对象返回
     * 1,返回值类型File
     * 2,参数列表无
     */
    public static File getFile() {
        Scanner sc = new Scanner(System.in);        //创建键盘录入对象
        System.out.println("请输入一个文件的路径");
        while(true) {
            String line = sc.nextLine();            //接收键盘录入的路径
            File file = new File(line);             //封装成File对象,然后对其判断
            if(!file.exists()) {
                System.out.println("您录入的文件路径不存在,请重新输入:");
            }else if(file.isDirectory()) {
                System.out.println("您录入的是文件夹路径,请重新输入:");
            }else {
                return file;    //直接return,整个方法结束,循环也结束了。
            }
        }
    }

}

录入数据拷贝到文件

  • 将键盘录入的数据拷贝到当前项目下的text.txt文件中,键盘录入数据当遇到quit时就退出
package com.heima.test;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;

public class Test3 {

    /**
     * 1,创建键盘录入对象
     * 2,创建输出流对象,关联text.txt文件
     * 3,定义无限循环
     * 4,遇到quit就退出循环
     * 5,如果不quit,就将内容写出
     * 6,关闭流
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        //1,创建键盘录入对象
        Scanner sc = new Scanner(System.in);
        //2,创建输出流对象,关联text.txt文件
        FileOutputStream fos = new FileOutputStream("text.txt");
        System.out.println("请输入数据:");
        //3,定义无限循环
        while(true) {
            String line = sc.nextLine();        //将键盘录入的数据存储在line中
            //4,遇到quit就退出循环
            if("quit".equals(line)) {
                break;
            }
            //5,如果不quit,就将内容写出
            fos.write(line.getBytes());         //字符串写出必须转换成字节数组
            fos.write("\r\n".getBytes());       //将换行写入
        }
        //6,关闭流
        fos.close();
    }

}

字符流FileReader

  • 1.字符流是什么
    • 字符流是可以直接读写字符的IO流
    • 字符流读取字符, 就要先读取到字节数据, 然后转为字符. 如果要写出字符, 需要把字符转为字节再写出.
  • 2.FileReader
    • FileReader类的read()方法可以按照字符大小读取
package com.heima.chario;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class Demo1_FileReader {

    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("xxx.txt");
        int c;
        
        while((c = fr.read()) != -1) {          //通过项目默认的码表一次读取一个字符
            System.out.println((char)c);
        }
        
        fr.close();
    }

    public static void demo1() throws FileNotFoundException, IOException {
        FileReader fr = new FileReader("xxx.txt");
        int x = fr.read();
        System.out.println(x);
        char c = (char)x;
        System.out.println(c);
        fr.close();
    }

}

字符流FileWriter

  • FileWriter类的write()方法可以自动把字符转为字节写出
package com.heima.chario;

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

public class Demo2_FileWriter {

    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("yyy.txt");
        fw.write("大家好,基础班快接近尾声了");
        fw.write(97);       //写入单个字符
        fw.close();
    }

}

字符流的拷贝

package com.heima.chario;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Demo3_Copy {

    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("xxx.txt");
        FileWriter fw = new FileWriter("zzz.txt");
        
        int c;
        while((c = fr.read()) != -1) {
            fw.write(c);
        }
        
        fr.close();
        fw.close(); //Writer类中有一个缓冲区,大小为1024的字符数组,如果不关流,内容会留在缓冲区。
    }

}

什么情况下使用字符流

  • 字符流也可以拷贝文本文件, 但不推荐使用. 因为读取时会把字节转为字符, 写出时还要把字符转回字节.字节流可以不需要转换过程。
  • 程序需要读取一段文本, 或者需要写出一段文本的时候可以使用字符流(只读或只写)
    • 读取的时候是按照字符的大小读取的,不会出现半个中文
    • 写出的时候可以直接将字符串写出,不用转换为字节数组


      字符流和字节流哪个拷贝纯文本更好.png

字符流是否可以拷贝非纯文本的文件

  • 不可以拷贝非纯文本的文件
  • 因为在读的时候会将字节转换为字符,在转换过程中,可能找不到对应的字符,就会用?代替,写出的时候会将字符转换成字节写出去
  • 如果是?,直接写出,这样写出之后的文件就乱了,看不了了

自定义字符数组的拷贝和带缓冲的字符流

  • BufferedReader的read()方法读取字符时会一次读取若干字符到缓冲区, 然后逐个返回给程序, 降低读取文件的次数, 提高效率
  • BufferedWriter的write()方法写出字符时会先写到缓冲区, 缓冲区写满时才会写到文件, 降低写文件的次数, 提高效率
package com.heima.chario;

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

public class Demo3 {

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("xxx.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("yyy.txt"));
        
        int c;
        while((c = br.read()) != -1) {
            bw.write(c);
        }
        
        br.close();
        bw.close();
    }

    public static void demo1() throws FileNotFoundException, IOException {
        FileReader fr = new FileReader("xxx.txt");
        FileWriter fw = new FileWriter("yyy.txt");
        
        char[] arr = new char[1024];
        int len;
        while((len = fr.read(arr)) != -1) { //将文件上的数据读取到字符数组中
            fw.write(arr,0,len);            //将字符数组中的数据写到文件上
        }
        
        fr.close();
        fw.close();
    }

}

readLine()和newLine()方法

  • BufferedReader的readLine()方法可以读取一行字符(不包含换行符号)
  • BufferedWriter的newLine()可以输出一个跨平台的换行符号"\r\n"
package com.heima.chario;

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

public class Demo4_Buffered {

    /**
     * 带缓冲区的流中的特殊方法
     * readLine()
     * newLine()与\r\n的区别
     * newLine()跨平台
     * \r\n只支持windows系统
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("zzz.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("aaa.txt"));
        
        String line;
        while((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();           //写出回车换行符
            //bw.write("\r\n");     //写出回车换行符
        }
        
        br.close();
        bw.close();
    }

    public static void demo1() throws FileNotFoundException, IOException {
        BufferedReader br = new BufferedReader(new FileReader("zzz.txt"));
        String line;
        
        while((line = br.readLine()) != null) { //readLine返回的是字符串对象,如果没读到就会返回null
            System.out.println(line);
        }
        
        br.close();
    }

}

将文本反转

  • 将一个文本文档上的文本反转,第一行和倒数第一行交换,第二行和倒数第二行交换
package com.heima.test;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

public class Test1 {

    public static void main(String[] args) throws IOException {
        //流对象尽量晚开早关
        // 1,创建输入输出流对象
        BufferedReader br = new BufferedReader(new FileReader("zzz.txt"));  
        // 2,创建集合对象
        ArrayList<String> list = new ArrayList<>();
        // 3,将读到的数据存储在集合中
        String line;
        while((line = br.readLine()) != null) {
            list.add(line);
        }
        br.close();
        // 4,倒着遍历集合将数据写在文件上
        BufferedWriter bw = new BufferedWriter(new FileWriter("revzzz.txt"));
        for (int i = list.size() - 1; i >= 0; i--) {
            bw.write(list.get(i));
            bw.newLine();
        }
        // 5,关流
        bw.close();
    }

}

LineNumberReader

  • LineNumberReader是BufferedReader的子类, 具有相同的功能, 并且可以统计行号
    • 调用getLineNumber()方法可以获取当前行号
    • 调用setLineNumber()方法可以设置当前行号
package com.heima.chario;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;

public class Demo5_LineNumberReader {

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        LineNumberReader lnr = new LineNumberReader(new FileReader("zzz.txt"));
        
        String line;
        lnr.setLineNumber(100); //设置行号,如果不设置,初始值是0
        while((line = lnr.readLine()) != null) {           //调用readLine(),行号就会加一
            System.out.println(lnr.getLineNumber() + ":" + line);  从100+1=101开始
        }
        lnr.close();
    }

}

装饰设计模式

package com.heima.chario;

public class Demo6_Wrap {
    //装饰设计模式的好处是:耦合性不强,被装饰的类的变化与装饰类的变化无关
    public static void main(String[] args) {
        HeiMaStudent hms = new HeiMaStudent(new Student());
        hms.code();
    }

}

interface Coder {
    public void code();
}

class Student implements Coder {

    public void code() {
        System.out.println("javase");
        System.out.println("javaweb");
    }
    
}

class HeiMaStudent implements Coder {
    //1,获取被装饰类的引用
    private Student s;                  //获取学生引用
    
    //2,在构造方法中传入被装饰类的对象
    public HeiMaStudent(Student s) {
        this.s = s;
    }
    
    //3,对原有的功能升级
    public void code() {
        s.code();
        System.out.println("ssh");
        System.out.println("数据库");
        System.out.println("大数据");
        System.out.println("...");
    }
}

使用指定的码表读写字符

  • FileReader是使用默认码表读取文件, 如果需要使用指定码表读取, 那么可以使用InputStreamReader(字节流,编码表)
  • FileWriter是使用默认码表写出文件, 如果需要使用指定码表写出, 那么可以使用OutputStreamWriter(字节流,编码表)
package com.heima.chario;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;

public class Demo7_TransIO {

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(     //更高效的读
                new InputStreamReader(new FileInputStream("utf-8.txt"),"utf-8"));
        BufferedWriter bw = new BufferedWriter(     //更高效的写
                new OutputStreamWriter(new FileOutputStream("gbk.txt"),"gbk"));
        int c;
        while((c = br.read()) != -1) {
            bw.write(c);
        }
        
        br.close();
        bw.close();
    }

    public static void demo2() throws UnsupportedEncodingException,
            FileNotFoundException, IOException {
        InputStreamReader isr = new             //指定码表读字符
                InputStreamReader(new FileInputStream("utf-8.txt"), "utf-8");
        OutputStreamWriter osw = new            //指定码表写字符
                OutputStreamWriter(new FileOutputStream("gbk.txt"),"gbk");

        int c;
        while((c = isr.read()) != -1) {
            osw.write(c);
        }
        
        isr.close();
        osw.close();
    }

    public static void demo1() throws FileNotFoundException, IOException {
        //用默认编码表读写出现乱码
        FileReader fr = new FileReader("utf-8.txt");
        FileWriter fw = new FileWriter("gbk.txt");
        
        int c;
        while((c = fr.read()) != -1) {
            fw.write(c);
        }
        
        fr.close();
        fw.close();
    }

}
转换流.png

获取文本上字符出现的次数

package com.heima.test;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.TreeMap;

public class Test3 {

    /**
     * 获取一个文本上每个字符出现的次数,将结果写在times.txt上
     * 分析:
     * 1,创建带缓冲的输入流对象
     * 2,创建双列集合对象TreeMap
     * 3,将读到的字符存储在双列集合中,存储的时候要做判断,如果不包含这个键,就将键和1存储
     * 如果包含这个键,就将该键和值加1存储
     * 4,关闭输入流,创建输出流对象
     * 5,遍历集合将集合中的内容写到times.txt中
     * 6,关闭输出流
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        //1,创建带缓冲的输入流对象
        BufferedReader br = new BufferedReader(new FileReader("zzz.txt"));
        //2,创建双列集合对象TreeMap
        TreeMap<Character, Integer> tm = new TreeMap<>();
        //3,将读到的字符存储在双列集合中,存储的时候要做判断,如果不包含这个键,就将键和1存储
        //如果包含这个键,就将该键和值加1存储
        int ch;
        while((ch = br.read()) != -1) {
            char c = (char)ch;          //强制类型转换
            /*if(!tm.containsKey(c)) {
                tm.put(c, 1);
            }else {
                tm.put(c, tm.get(c) + 1);
            }*/
            tm.put(c, !tm.containsKey(c) ? 1 : tm.get(c) + 1);
        }
        //4,关闭输入流,创建输出流对象
        br.close();
        BufferedWriter bw = new BufferedWriter(new FileWriter("times.txt"));
        //5,遍历集合将集合中的内容写到times.txt中
        for (Character key : tm.keySet()) {
            switch (key) {
            case '\t':
                bw.write("\\t" + "=" + tm.get(key));
                break;
            case '\n':
                bw.write("\\n" + "=" + tm.get(key));
                break;
            case '\r':
                bw.write("\\r" + "=" + tm.get(key));
                break;
            default:
                bw.write(key + "=" + tm.get(key));      //写出键和值
                break;
            }           
            bw.newLine();
        }
        //6,关闭输出流
        bw.close();
    }

}

试用版软件

package com.heima.test;

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

public class Test4 {

    /**
     * * 当我们下载一个试用版软件,没有购买正版的时候,每执行一次就会提醒我们还有多少次使用机会用学过的IO流知识,
     * 模拟试用版软件,试用10次机会,执行一次就提示一次您还有几次机会,如果次数到了提示请购买正版
     * 1,创建带缓冲的输入流对象,因为要使用readLine方法,这样可以保证数据的原样性
     * 2,将读到的字符串转换为int数
     * 3,对int数进行判断,如果大于0,就将其一1写回去,如果不大于0,就提示请购买正版
     * 4,在if判断中要将-1的结果打印,并将结果通过输出流写在文件上
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        //1,创建带缓冲的输入流对象,因为要使用readLine方法,这样可以保证数据的原样性
        BufferedReader br = new BufferedReader(new FileReader("config.txt"));
        //2,将读到的字符串转换为int数
        String line = br.readLine();
        int times = Integer.parseInt(line);     //将数字字符串转换为数字
        //3,对int数进行判断,如果大于0,就将其一1写回去,如果不大于0,就提示请购买正版
        if(times > 0) {
            //4,在if判断中要将-1的结果打印,并将结果通过输出流写在文件上
            System.out.println("您还有" + times-- + "次机会");
            FileWriter fw = new FileWriter("config.txt");
            fw.write(times + "");
            fw.close();
        }else {
            System.out.println("您的试用次数已到,请购买正版");
        }
        //关闭流
        br.close();
    }

}

递归

  • 递归:方法自己调用自己
  • 递归的弊端:不能调用次数过多,容易导致栈内存溢出
  • 递归的好处:不用知道循环次数
  • 构造方法是否可以递归调用?
    • 构造方法不能使用递归调用
  • 递归调用是否必须有返回值?
    • 不一定,可以有,也可以没有

练习

package com.heima.test;

import java.io.File;
import java.util.Scanner;

public class Test5 {

    /**
     * 需求:从键盘输入接收一个文件夹路径,打印出该文件夹下所有的.java文件名
     * 
     * 分析:
     * 从键盘接收一个文件夹路径
     * 1,如果录入的是不存在,给与提示
     * 2,如果录入的是文件路径,给予提示
     * 3,如果是文件夹路径,直接返回
     * 
     * 打印出该文件夹下的所有.java文件名
     * 1,获取到该文件夹路径下的所有的文件和文件夹,存储在File数组中
     * 2,遍历数组,对每一个文件或文件夹做判断
     * 3,如果是文件,并且后缀是.java的就打印
     * 4,如果是文件夹,就递归调用
     */
    public static void main(String[] args) {
        File dir = getDir();
        printJavaFile(dir);
    }
    
    /*
     * 获取键盘录入的文件夹路径
     * 1,返回值类型File
     * 2,不需要有参数
     */
    public static File getDir() {
        Scanner sc = new Scanner(System.in);        //创建键盘录入对象
        System.out.println("请输入一个文件夹路径");
        while(true) {
            String line = sc.nextLine();        //将键盘录入的文件夹路径存储
            File dir = new File(line);          //封装成File对象
            if(!dir.exists()) {
                System.out.println("您录入的文件夹路径不存在,请重新输入");
            }else if(dir.isFile()) {
                System.out.println("您录入的是文件路径,请重新输入文件夹路径");
            }else {
                return dir;
            }
        }
    }
    /*
     * 获取文件夹路径下的所有.java文件
     * 1,返回值类型void
     * 2,参数列表File dir
     */
    public static void printJavaFile(File dir) {
        //1,获取到该文件夹路径下的所有的文件和文件夹,存储在File数组中
        File[] subFiles = dir.listFiles();
        //2,遍历数组,对每一个文件或文件夹做判断
        for (File subFile : subFiles) {
            //3,如果是文件,并且后缀是.java的就打印
            if(subFile.isFile() && subFile.getName().endsWith(".java")) {
                System.out.println(subFile);
            //4,如果是文件夹,就递归调用
            }else if (subFile.isDirectory()) {
                printJavaFile(subFile);
            }
        }
    }

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,565评论 18 399
  • 整理来自互联网 1,JDK:Java Development Kit,java的开发和运行环境,java的开发工具...
    Ncompass阅读 1,534评论 0 6
  • 觉得楷书还是基础,打好基础,才能有所提高啊
    请叫我喵大叔阅读 208评论 0 0
  • 焦点网络班第一期 郑州何琴 坚持分享第700天 这两天眼看快过年了,而我们今年准备回老家过年,但是点点的作业比较...
    依然化蝶阅读 143评论 0 0
  • 防止xss注入 xss攻击从发生的时间段来看,主要有两种防御方式,第一种是防止xss注入,第二种则是在xss注入之...
    Taniffer阅读 568评论 1 0