Java 字节区/字符区缓冲流

零、复习昨日

File:通过路径代表一个文件或目录
方法:创建新,查找类

一、作业

给定路径删除文件夹

public static void main(String[] args){
        deletDir(new File("F:\\qf"));
    }

    // 删除文件夹
    public static void deletDir(File file){
        File[] files = file.listFiles();
        for (File file1 : files) {
            if (file1.isFile()){
                file1.delete();
            } else {
                deletDir(file1);
            }
        }
        file.delete();
    }

二、缓冲字节流

拷贝一首歌

   public static void main(String[] args) throws Exception {
        // 拷贝歌曲,耗时 183372毫秒
        long begin = System.currentTimeMillis( );
        FileInputStream fis = new FileInputStream("E:\\Angel.mp3");
        FileOutputStream fos = new FileOutputStream("E:\\Angel2.mp3");

        int b = -1;
        while((b = fis.read()) != -1) {
            fos.write(b);
        }

        fis.close();
        fos.close();
        long end = System.currentTimeMillis( );
        System.out.println("拷贝歌曲,耗时 " + (end - begin) + "毫秒" );
    }

很慢很慢~~

原因:一次读写一个字节,但是歌曲10M的有1100万多个字节


一次读多个写多个,就是 缓冲区字节流

缓冲区字节输入流 BufferedInputStream(没有空参);缓冲区字节输出流 BufferedOutputStream。
之所以快,是因为他们==内部有一个缓冲区数组(长度8192)==,一次读取或者写出的时候通过数组完成,即一次读取或者写出多个
使用缓冲区输入/输出流,需要给构造方法传入对应输入/输出流(高效流)

   public static void main(String[] args) throws Exception {
        // 拷贝歌曲,耗时 183372毫秒
        long begin = System.currentTimeMillis( );
        FileInputStream fis = new FileInputStream("E:\\Angel.mp3");
        FileOutputStream fos = new FileOutputStream("E:\\Angel2.mp3");

        // 创建缓冲区输入.输出流
        BufferedInputStream bis = new BufferedInputStream(fis);
        BufferedOutputStream bos = new BufferedOutputStream(fos);


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

        bis.close();
        bos.close();

        // 内部是数组传输数据,最后一次输出数据时,数组不一定装满
        // 如果执行close,会关流的同时会强制刷新剩余数据输出
        // 也可以执行flush手动刷新
        // bos.flush();

        long end = System.currentTimeMillis( );
        System.out.println("拷贝歌曲,耗时 " + (end - begin) + "毫秒" );

    }

三、字符流

字节流适合读取二进制文件,读取字符数据可能会乱码!建议读取字符,采取字符流!
字符流有两个抽象父类
Reader (字符输入流)
Writer (字符输出流)

一般使用其子类
FileReader
FileWriter

3.1 FileReader

构造方法
FileReader(File file) 在给定从中读取数据的 File 的情况下创建一个新 FileReader。
FileReader(String fileName) 在给定从中读取数据的文件名的情况下创建一个新 FileReader。
方法
int read() 读取单个字符。 读完末尾返回-1
int read(char[] cbuf) 将字符读入数组。
void close() 关闭该流并释放与之关联的所有资源。
public static void main(String[] args) throws Exception {
    FileReader fileReader = new FileReader("F:\\qf\\a.txt");
    int ch = -1;
    while ((ch = fileReader.read()) != -1){
        System.out.print((char) ch);
    }
    fileReader.close();
}
FileReader fileReader = new FileReader("F:\\qf\\a.txt");

	char[] chars = new char[4];
    fileReader.read(chars);
    System.out.println(chars);

        fileReader.close();

3.2 FileWriter

FileWriter在创建时,内部默认构造一个缓冲数组,数组长度为 1kb = 1024字节
构造方法
FileWriter(File file) 根据给定的 File 对象构造一个 FileWriter 对象。
FileWriter(File file, boolean append) 根据给定的 File 对象构造一个 FileWriter 对象。
FileWriter(String fileName) 根据给定的文件名构造一个 FileWriter 对象。
FileWriter(String fileName, boolean append) 根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。

append指定成true,在原文件后面追加,指定成false,覆盖原文件
如果不知道,默认就是false
方法
void close() 关闭此流,但要先刷新它。
void flush() 刷新该流的缓冲。
void write(char[] cbuf) 写入字符数组。
void write(int c) 写入单个字符。
void write(String str) 写入字符串。
void write(String str, int off, int len) 写入字符串的某一部分。
FileWriter fileWriter = new FileWriter("F:\\qf\\a.txt");
// 写字符
fileWriter.write('j');
// 写字符串
fileWriter.write("java");

// 写字符数组
char[] chars = {'我','爱','祖','国'};
fileWriter.write(chars);

// 写字符串数组
String str = "我爱祖国!";
fileWriter.write(str,2,3);

fileWriter.flush();

3.3 练习:复制小说

FileReader fileReader = null;
FileWriter fileWriter = null;
try{
    fileReader = new FileReader("F:\\java素材\\Java书籍\\《雪中悍刀行》.txt");
    fileWriter = new FileWriter("F:\\qf\\《雪中悍刀行》.txt");

    int ch = -1;
    while ((ch = fileReader.read()) != -1){
        fileWriter.write((char)ch);
    }
} catch (IOException e){
    e.printStackTrace();
} finally {
    try {
        fileReader.close();
        fileWriter.close();
    } catch (IOException e){
        e.printStackTrace();
    }
}

3.4 练习

使用字符流把a文件中的数据转换后写到b文件中

要求:1) 大写转换为小写 2)小写转换为大写 3)删除数字

四、缓冲字符流

BufferedReader BufferedWriter
缓冲区字符输入输出流,内部在创建对象是会构建一个缓冲区数组(长度8192)
BufferedReader

构造方法
BufferedReader (Reader in) 创建一个使用默认大小输入缓冲区的缓冲字符输入流

方法
int read() 读取单个字符。
String readLine() 读取一个文本行。
void close() 关闭该流并释放与之关联的所有资源。
BufferedWriter

构造方法
BufferedWriter(Writer out) 创建一个使用默认大小输出缓冲区的缓冲字符输出流。

方法
void close() 关闭此流,但要先刷新它。
void flush() 刷新该流的缓冲。
void newLine() 写入一个行分隔符。
void write(int c) 写入单个字符。
void write(String s) 写入字符串
    public static void main(String[] args) {

        long begin = System.currentTimeMillis( );

        FileReader fr = null;
        FileWriter fw = null;
        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
            fr = new FileReader("E:\\《雪中悍刀行》.txt");
            fw = new FileWriter("E:\\血刀.txt");

            br = new BufferedReader(fr);
            bw = new BufferedWriter(fw);


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

            String line = null;
            // 一次读取一行,读取到换行终止符结束并返回,但是不包含终止符
            while((line = br.readLine()) != null) {
                bw.write(line); // 写一行字符串
                // 写出一个换行符
                // bw.write("\r\n");
                bw.newLine();
            }


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

            try {
                br.close();
                bw.close();
            } catch (IOException e) {
                e.printStackTrace( );
            }
        }
        long end = System.currentTimeMillis( );
        System.out.println("拷贝小说,耗时 " + (end - begin) + "毫秒" );
    }
练习

读取一个文本,按行倒着输出,即读取的第一行输出在最后一行,读取的第二行,输出在倒数第二行.

思路: 不能读完直接输出了,而是读一行,向集合中存一行.读取完毕后,倒着遍历集合即可

FileReader fr = new FileReader("F:\\qf\\a.txt");
        FileWriter fw = new FileWriter("F:\\qf\\b.txt");
        BufferedReader br = new BufferedReader(fr);
        BufferedWriter bw = new BufferedWriter(fw);

        ArrayList<String> list = new ArrayList<>();
        String line = null;
        while ((line = br.readLine()) != null){
            list.add(line);
        }

        for (int i = list.size() - 1; i >= 0; i--) {
            bw.write(list.get(i));
            bw.newLine();
        }

        br.close();
        bw.close();
将上面歌词内容存放到本地磁盘D根目录,文件命名为 word.txt
选择合适的IO流读取word.txt文件的内容
统计每个单词出现的次数(单词忽略大小写)
如果出现组合单词如 you're按一个单词处理
将统计的结果存储到本地磁盘D根目录下的wordcount.txt文件
【该题使用缓冲字符流更好】
wordcout.txt每行数据个数如下
you --> 9次
my --> 9次
I --> 9次
FileReader fr = new FileReader("F:/qf\\word.txt");
FileWriter fw = new FileWriter("F:/qf\\wordCount.txt");
BufferedReader br = new BufferedReader(fr);
BufferedWriter bw = new BufferedWriter(fw);

HashMap<String,Integer> map = new HashMap<>();
String line = null;
while ((line = br.readLine()) != null){
    String[] str = line.split(" ");
    for (String s : str) {
        String s1 = s.toLowerCase();
        if (map.containsKey(s1)){
            Integer count = map.get(s1);
            count++;
            map.put(s1,count);
        } else {
            map.put(s1,1);
        }
    }
}

// 输出
Set<Map.Entry<String, Integer>> entries = map.entrySet();
Iterator<Map.Entry<String, Integer>> iterator = entries.iterator();
for (Map.Entry<String, Integer> entry : entries) {
    bw.write(entry.getKey()+"--->"+entry.getValue());
    bw.newLine();
}

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

五、总结

画思维导图 https://www.processon.com/view/link/6360e893f346fb33540a61c1

六、匿名内部类

思考一个问题?
假如有一个接口,现在让你创建一个接口的实现类对象,该怎么做?
换句话,有个方法,参数列表是接口,应该如何调用?

解决:
先创建一个类,实现接口,重写方法
创建对象
现在有个更简单的写法,可以不用创建类就可以实现出一个接口的实现类
// 接口
public interface USB {
    void run();
}
public static void main(String[] args) {
    // 有一个接口,现在让你创建一个接口的实现类对象
    // new USBImpl();
    // test(new USBImpl());

    // 就相当于是创建了USB接口的实现类,并且重写了方法
    // 这就是匿名内部类
    test(new USB(){
        @Override
        public void run() {
            System.out.println("匿名实现.." );
        }
    });

    // 这样是将匿名内部类,取了名字叫usb
    USB usb = new USB(){
        @Override
        public void run() {
            System.out.println("匿名实现.." );
        }
    };

    test(usb);
}

public static void test(USB usb) {
    usb.run();
}
总结: 匿名内部类就是简化了创建子类对象的过程.

实战

使用匿名内部类完成. 创建TreeSet时指定比较器.

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值