一、字符流
字节流适合读取二进制文件,读取字符数据可能会乱码!建议读取字符,采用字符流!
字符流有两个抽象父类
Reader (字符输入流 )
Writer (字符输出流)
一般使用其子类
FileReader
FileWriter
1.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 fr = new FileReader("a.txt");
int ch = -1;
while((ch = fr.read()) != -1) {
System.out.println((char)ch );
}
fr.close();
}
-------------------
FileReader fr = new FileReader("a.txt");
char[] chars = new char[4]; // 创建空字符数组
fr.read(chars); // 一次读取数组长度个字符,存储到数组中
System.out.println(Arrays.toString(chars ) );
fr.close();
1.2 FileWriter
FileWriter在创建时,内部默认构造一个缓冲数组,用于一次写出多个,大小是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) 写入字符串的某一部分。
public static void main(String[] args) throws Exception {
FileWriter fw = new FileWriter("a.txt");
// 写字符
fw.write('j');
// 写字符串
fw.write("java");
// 写字符数组
char[] chars = {'a','b','c'};
fw.write(chars);
// 写字符串中一部分内容
String str = "javabigdata";
fw.write(str,4,3);
// 因为有缓冲区,不关流的话有些数据无法输出
// 因为没有达到缓冲区大小
//fw.close();
// 也可以强制刷新出来
fw.flush();
}
二、缓冲字符流
BufferedReader BufferedWriter缓冲区字符输入输出流,内部在创建对象时会构建一个长度为8192的缓冲数组.
ps: 查看构造方法源码...
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) 写入字符串
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();
练习
读取一个文本,按行倒着输出,即读取的第一行输出在最后一行,读取的第二行,输出在倒数第二行.
思路: 不能读完直接输出了,而是读一行,向集合中存一行.读取完毕后,倒着遍历集合即可
public static void main(String[] args) {
long begin = System.currentTimeMillis( );
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader("E:\\a.txt"));
bw = new BufferedWriter(new FileWriter("E:\\a2.txt"));
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--) {
String s = list.get(i);
bw.write(s);
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) + "毫秒" );
}
三、匿名内部类
假如有一个接口,现在让你创建一个接口的实现类对象,该怎么做?换句话,有个方法,参数列表是接口,应该如何调用?
解决:
先创建一个类,实现接口,重写方法创建对象
现在有个更简单的写法,可以不用创建类就可以实现出一个接口的实现类
// 接口
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();
}

总结: 匿名内部类就是简化了创建子类对象的过程.