一、IO流补充
1、Reader、Writer
Reader 所有字符输入流统一的父类 抽象类
int read()
int read(char[] data)
int read(char[] data,int offset,int length)
Writer 所有字符输出流统一的父类 抽象类
write(int data)
write(char[] data)
write(char[] data,int offset,int length)
2、FileReader、FileWriter
FileReader 字符流 输入流 节点流
FileWriter 字符流 输出流 节点流
*: 它们都是节点流 构造方法允许传入String路径/File对象
*: 它们都是节点流 但是只能连接文件 不能连接目录
否则直接出现FileNotFoundException [拒绝访问!]
*: FileReader 最常用的是read(char[])
*: FileWriter 最常用的是write(char[],int,int)
*: FileReader 以-1作为读取结束的标识
*: FileWriter 是节点输出流
节点输出流创建对象的时候 如果连接的文件不存在
也会在创建流的那一刻自动创建出来 不需要手建
File类有个方法 createNewFile() 没讲
如果其连接的目录结构都不存在 将会直接触发异常
FileNotFoundException [系统找不到指定的路径]
所以File类 mkdirs() 一等优先级
*: FileWriter 是节点输出流 它有极强的杀伤性
如果创建对象的时候 连接的文件已经存在
也会被新的空白文件直接替换
如果需求是在原有内容的最后
追加连接新内容 则可以构造方法传参
指定追加模式开启
new FileWriter("abc.txt",true);
import java.io.*;
public class TestFileReader{public static void main(String[] args)throws Exception{FileReader fr = new FileReader("abc.txt");int data;while((data = fr.read())!=-1){System.out.print((char)data);}fr.close();}
}
3、BufferedReader 、BufferedWriter
BufferedReader 输入流 字符流 过滤流
BufferedWriter 输出流 字符流 过滤流
*: 作为过滤流的它们 给原本的流添加变长的缓冲空间
从而实现以一行(hang)为单位的读写
*: 它们都是过滤流 不能直接连接文件 只能连接其它的流
*: BufferedReader String readLine()
*: BufferedWriter write(String) + newLine()
*: BufferedReader 以null作为读取结束的标识
*: BufferedWriter 是带缓冲的输出流
务必注意及时清空缓冲 防止数据滞留缓冲区导致丢失
import java.io.*;
public class TestBufferedWriter{public static void main(String[] args)throws Exception{BufferedWriter bw = new BufferedWriter(new FileWriter("鹅鹅鹅.txt"));bw.write("鹅鹅鹅");bw.newLine();bw.write("鹅项向天歌");bw.newLine();bw.write("鹅毛浮绿水");bw.newLine();bw.write("鹅可能死了");bw.close();}
}
4、PrintWriter
PrintWriter 比 BufferedWriter优秀在哪些方面?
1.PrintWriter既可以当做节点流 又可以当做过滤流
构造方法允许传入 String路径/File对象/流
2.PrintWriter既可以连接字节流 又可以连接字符流
构造方法允许传入 OutputStream / Writer
3.PrintWriter作为节点流使用的时候
构造方法第二个参数 可以指定字符编码
new PrintWriter("abc.txt","utf-8");
4.PrintWriter作为过滤流使用的时候
构造方法第二个参数 可以指定自动清空缓冲
new PrintWriter(new FileWriter("a.txt"),true);
5.PrintWriter 一行println() 等于write()+newLine()
6.我们对它的孪生兄弟 特别熟悉 PrintStream
System.out.println
二、BigOne
其实就是在递归调用来遍历所有文件的过程中,读取文件的每一行,计算有效的代码量。
import java.util.*;
import java.io.*;
import java.text.*;public class Exec5{static Map<String,Integer> map = new HashMap<>();static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");public static void main(String[] args)throws Exception{File file = new File("F:\\Java课程");File[] fs = file.listFiles();for(File f : fs){search(f);}PrintWriter pw = new PrintWriter("统计报告.txt");Map<Integer,String> data = new TreeMap<>((a,b) -> a == b ? 1 : b-a);map.forEach((k,v) -> data.put(v,k));data.forEach((v,k) -> System.out.println(k +" : " + v) );data.forEach((v,k) -> pw.println(k +" : " + v));pw.close();}public static void search(File file)throws Exception{File[] ds = file.listFiles((x) -> x.isDirectory());File[] js = file.listFiles((x) -> x.isFile() && x.getName().toLowerCase().endsWith(".java"));if(ds == null)return;boolean isCode = true;for(File d : ds){search(d);}for(File j : js){int sum = 0;BufferedReader br = new BufferedReader(new FileReader(j));String ax = br.readLine();while((ax = br.readLine()) != null){if(ax.trim().length() == 0)continue;if(ax.trim().startsWith("/*")){isCode = false;}if(ax.trim().endsWith("*/")){isCode = true;continue;}sum++;}br.close();long time = j.lastModified();String final_time = sdf.format(time);if(map.containsKey(final_time)){map.put(final_time,map.get(final_time) + sum);}else{map.put(final_time,sum);}}}}