三、节点流(或文件流)
读取文件
@Test public void test() { FileInputStream fis = null; try { //1.指明要操作的文件 File file = new File("hello.txt"); //2.提供具体的流 fis = new FileInputStream(file); //3.读数据 byte[] buffer = new byte[5]; int len;//记录每次读取的字节的个数 while ((len = fis.read(buffer)) != -1) { String str = new String(buffer, 0, len); System.out.println(str); } } catch (IOException e) { e.printStackTrace(); } finally { if (fis != null) { //4.关资源 try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
写入文件
@Test public void testFileWriter() { FileWriter fw = null; try { //1.提供File类的对象,指明写出到的文件 File file = new File("hello1.txt"); //2.提供FileWriter的对象,用于数据的写出 fw = new FileWriter(file, false); //3.写出的操作 fw.write("I hava a dream\n"); fw.write("aoligei!"); } catch (IOException e) { e.printStackTrace(); } finally { //4.流资源的关闭 try { if (fw != null) { fw.close(); } } catch (IOException e) { e.printStackTrace(); } } }
节点流(或文件流):注意点
四、缓冲流
什么是缓冲流?
为了提高数据读写的速度,JavaAPI提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组,缺省使用8192个字节(8Kb)的缓冲区。
缓冲流要“套接”在相应的节点流之上,根据数据操作单位可以把缓冲流分为:
BufferedInputStream 和 BufferedOutputStream
BufferedReader 和 BufferedWriter
怎么工作的?
当读取数据时,数据按块读入缓冲区,其后的读操作则直接访问缓冲区
当使用BufferedInputStream读取字节文件时,BufferedInputStream会一 次性从文件中读取8192个(8Kb), 存在缓冲区中,直到缓冲区装满了,才重新从文件中读取下一个8192个字节数组
向流中写入字节时,不会直接写到文件,先写到缓冲区中直到缓冲区写满,BufferedOutputStream才会把缓冲区中的数据一 次性写到文件里。使用方法flush()可以强制将缓冲区的内容全部写入输出流
关闭流的顺序和打开流的顺序相反。只要关闭最外层流即可,关闭最外层流也会相应关闭内层节点流
flush()方法的使用:手动将buffer中内容写入文件
如果是带缓冲区的流对象的close()方法,不但会关闭流,还会在关闭流之前刷新缓冲区,关闭后不能再写出
图解缓冲流
实例
@Test public void BufferdStreamTest() { BufferedInputStream bis = null; BufferedOutputStream bos = null; try { //1.造文件 File srcFile = new File("cxk.jpg"); File destFile = new File("cxk3.jpg"); //2.造流 //2.1节点流 FileInputStream fis = new FileInputStream(srcFile); FileOutputStream fos = new FileOutputStream(destFile); //2.2缓冲流 bis = new BufferedInputStream(fis); bos = new BufferedOutputStream(fos); //3.复制的细节:读取写入 byte[] buffer = new byte[10]; int len; while ((len = bis.read(buffer)) != -1) { bos.write(buffer, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { //4.资源关闭 //要求:先关闭外层的流,在关闭内层的流 //说明:关闭外层流的同时,内层流会自动进行关闭,关闭内层流的操作可以省略 // fos.close(); // fis.close(); if (bos != null) { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } if (bis != null) { try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
缓冲流练习
package com.caq.exer; import org.junit.Test; import java.io.*; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * 获取文本上字符出现的次数,把数据写入文件 * * 思路: * 1.遍历文本每一个字符 * 2.字符出现的次数存在Map中 * * Map<Character,Integer> map = new HashMap<Character,Integer>(); * map.put('a',18); * map.put('你',2); * * 3.把map中的数据写入文件 * */ public class WordCount { /* 说明:如果使用单元测试,文件相对路径为当前module 如果使用main()测试,文件相对路径为当前工程 */ @Test public void testWordCount() { FileReader fr = null; BufferedWriter bw = null; try { //1.创建Map集合 Map<Character, Integer> map = new HashMap<Character, Integer>(); //2.遍历每一个字符,每一个字符出现的次数放到map中 fr = new FileReader("dbcp.txt"); int c = 0; while ((c = fr.read()) != -1) { //int 还原 char char ch = (char) c; //判断char是否在map中第一次出现 if (map.get(ch) == null) { map.put(ch, 1); } else { map.put(ch, map.get(ch) + 1); } } //3.把map中数据存在文件count.txt //3.1 创建Writer bw = new BufferedWriter(new FileWriter("wordcount.txt")); //3.2 遍历map,再写入数据 Set<Map.Entry<Character, Integer>> entrySet = map.entrySet(); for (Map.Entry<Character, Integer> entry : entrySet) { switch (entry.getKey()) { case ' ': bw.write("空格=" + entry.getValue()); break; case '\t'://\t表示tab 键字符 bw.write("tab键=" + entry.getValue()); break; case '\r':// bw.write("回车=" + entry.getValue()); break; case '\n':// bw.write("换行=" + entry.getValue()); break; default: bw.write(entry.getKey() + "=" + entry.getValue()); break; } bw.newLine(); } } catch (IOException e) { e.printStackTrace(); } finally { //4.关流 if (fr != null) { try { fr.close(); } catch (IOException e) { e.printStackTrace(); } } if (bw != null) { try { bw.close(); } catch (IOException e) { e.printStackTrace(); } } } } }