字符流:以字符为单位进行读取
使用场景:如果读取文本内容时推荐使用字符流进行读取(一个汉字占用的两个字节(一个字符))
两个抽象基类
Reader:用于读取字符流的抽象类。
FileReader:是Reader的子类
FileReader的构造函数
FileReader(File file) 在给定从中读取数据的 File 的情况下创建一个新 FileReader。
FileReader(String fileName) 在给定从中读取数据的文件名的情况下创建一个新 FileReader。
注意:在创建FileReader对象时需要捕获一个检查异常:FileNotFoundException
常用方法:
int read():读取单个字符。 有一个检查异常需要捕获IOException
int read(char[] cbuf, int offset,int length):将字符读入数组中的某一部分。
close() 关闭该流并释放与之关联的所有资源。 有一个检查异常需要捕获IOException
Writer:.......
public class TestFileReader { public static void main(String[] args) { FileReader fileReader=null; try { //1.将文件转成文件字符输入流 fileReader = new FileReader("D:/aa.txt"); int len; //2.使用read方法循环读取文件内容 while((len=fileReader.read())!=-1){ char c = (char)len; System.out.print(c); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } }
String(char[] value):分配一个新的 String,使其表示字符数组参数中当前包含的字符序列
String(char[] value, int offset, int count) 分配一个新的 String,它包含取自字符数组参数一个子数组的字符。
public class TestFileReader2 { public static void main(String[] args) { FileReader fileReader=null; try { //1.将文件转成文件字符输入流 fileReader = new FileReader("D:/aa.txt"); char[] cs = new char[1024]; //2.使用read方法循环读取文件内容 // fileReader.read(cs); //将char类型的数组cs转换成字符串 // String str = new String(cs); int len = fileReader.read(cs); String str = new String(cs,0,len); System.out.println(str); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } }
Writer:写入字符流的抽象类
FileWriter类:Writer的子类,用法与FileOutputStream(读写单位为字节)类似 ,读写单位为字符
构造函数:
FileWriter(File file)根据给定的 File 对象构造一个 FileWriter 对象。
FileWriter(File file, boolean append) 根据给定的 File 对象构造一个 FileWriter 对象。
append代表是否追加内容,如果值为false将发生覆盖,否则追加内容。
FileWriter(String fileName) 根据给定的文件名构造一个 FileWriter 对象。
FileWriter(String fileName, boolean append) 根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。
常用方法:
write(int c):写入单个字符。
write(String str):写入字符串。
write(char[] cbuf, int off,int len):写入字符数组的某一部分。
write(String str,int off,int len):写入字符串的某一部分。
flush():刷新该流的缓冲。
close():关闭此流,但要先刷新它
public class TestFileWriter { public static void main(String[] args) { File file = new File("D:/test.txt"); FileWriter fw=null; try { // fw = new FileWriter(file); fw = new FileWriter(file,true); fw.write("FileWriter测试!"); fw.write("测试2!"); fw.flush();//刷新该流的缓冲 } catch (IOException e) { e.printStackTrace(); }finally{ try { fw.close();//关闭流时会调用flush()方法刷新缓冲流 } catch (IOException e) { e.printStackTrace(); } } } }
捕获异常的快捷键:alt+shift+z
BufferedReader类:继承了Reader类,带缓冲区的输入流,提高读的效率
按功能划分属于处理流,必须结合节点流进行使用,不能单独使用
构造函数:
BufferedReader(Reader in) 创建一个使用默认大小输入缓冲区的缓冲字符输入流。
BufferedReader(Reader in, int size) 创建一个使用指定大小输入缓冲区的缓冲字符输入流。
常用方法:
readLine() 读取一个文本行。
close() 关闭该流并释放与之关联的所有资源
public class TestBufferedReader { public static void main(String[] args) { //1.创建FileReader对象(节点流) FileReader fr=null; BufferedReader br=null; try { fr = new FileReader("D:/aa.txt"); //2.创建字符输入缓冲流BufferedReader br = new BufferedReader(fr); //3.读取数据 String str; while((str=br.readLine())!=null){ System.out.println(str); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ try { //4.是否资源 br.close(); fr.close(); } catch (IOException e) { e.printStackTrace(); } } } }
BufferedWriter:继承了Writer类,将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
按功能划分属于处理流,必须结合Writer(节点流)进行使用
构造函数:
BufferedWriter(Writer out):创建一个使用默认大小输出缓冲区的缓冲字符输出流。
BufferedWriter(Writer out, int sz): 创建一个使用给定大小输出缓冲区的新缓冲字符输出流
常用的方法:
write(int c) : 写入单个字符
write(String str) : 写入字符串
flush():刷新该流的缓冲。
close():关闭此流,但要先刷新它。
public class TestBufferedWriter { public static void main(String[] args) { File file = new File("D:/test2.txt"); FileWriter fw=null; BufferedWriter bw=null; try { fw = new FileWriter(file); bw = new BufferedWriter(fw); bw.write("hello"); bw.newLine();//写入一个行分隔符(换行) bw.write("hello again!"); bw.newLine(); bw.write("你好!"); bw.flush(); } catch (IOException e) { e.printStackTrace(); }finally{ try { bw.close(); fw.close();//关闭流时会调用flush()方法刷新缓冲流 } catch (IOException e) { e.printStackTrace(); } } } }
统计某个文件夹下(包含子文件和文件)的所有代码的行数
实现思路:
1.获取该文件夹和子文件下的所有文件(递归)
2.使用BufferedReader中的readLine()读取行数据
技能点:
File类的常用方法: listFiles(),isDirectory(),exist()
递归调用
FileReader
BufferedReader: readLine()
public class CodeCounter { static long count=0; /** * 统计指定文件下的代码行数 * @param file * @throws IOException */ public static void calcCode(File file) throws IOException{ //判断文件目录是否存在 if(file.exists()){ //获取该目录下所有的子文件或子目录 File[] fs = file.listFiles(); for (File f : fs) { //判断是否为目录 if(f.isDirectory()){ calcCode(f);//递归调用 }else{ String fileName = f.getName(); //判断文件是否为java源文件(java源文件的后缀名为.java) if(fileName.endsWith(".java")){ FileReader fr = new FileReader(f); BufferedReader br = new BufferedReader(fr); while(br.readLine()!=null){ count++; } br.close(); fr.close(); } } } }else{ System.out.println("你要统计的目录不存在!"); } } public static void main(String[] args) { // File file = new File("D:/javacode"); File file = new File("F:/workspaces"); try { CodeCounter.calcCode(file); } catch (IOException e) { e.printStackTrace(); } System.out.println("代码总行数:"+CodeCounter.count); } }