1、节点流和处理流的概念
根据输入输出方式不同,我们划分了输入流和输出流;根据处理数据流的单位不同,我们划分了字节流和字符流;现在我们根据数据封装类型的不同划分节点流和处理流。
- 节点流
- 如果流封装的是某种特定的数据源,如文件、字符串、字符串数组等,则称为节点流
- 处理流
- 如果流封装的是其他的流对象,称之为处理流。处理流提供缓冲功能,提高读写效率
2、节点流和处理流的常用类
节点流中常用类:
- 字节输入流 FileInputStream
- 字节输出流 FileOutputStream
- 字符输入流 FileReader
- 字符输出流 FileWriter
处理流中常用类:
- 缓冲字节输出流 BufferedOutputStream
- 缓冲字节输入流 BufferedInputStream
- 缓冲字符输入流 BufferedReader
- 缓冲字符输出流 BufferedWriter
这里所谓的缓冲:就是对操作的数据进行了临时的缓存,从而提高读写的效率。
这样的描述可能不太容易理解,引用一段《Head First Java》中的描述,缓冲区类似超市里的购物推车:
使用缓冲区比没有使用的效率更高,实际上你确实可以直接使用FileWriter,调用write()来写文件,就像你在超市购物,你每拿一样东西就跑去收银台付一次账,如果没有像超市推车一样的缓冲区,你确实也能达到目的,但也累得不行,效率还很低。
而我们常说的flush(),实际上就是强制缓冲区立即写入,形象地说,就是马上把推车推到收银台去结一次账。
好了,这样你就一定能形象地理解缓冲的好处了,下面聊聊处理流的特点:
- 字符缓冲输入流提供了读取一行的方法readLine()
- 字符缓冲输出流提供了写入一个空行的方法newLine()
- 字符缓冲输出流,把写入的数据先写入到内存,再使用flush()方法将内存数据刷到硬盘上
需要注意的是,在使用close()关闭流之前,一定要先flush()一下,避免数据的丢失。离开超市之前不结账,你觉得最后能把东西拿回家吗?
3、示例
3.1 示例代码
我们以读取硬盘上某个txt文本中的信息并写入到另一个文件为例,假如在电脑桌面有文件test.txt,内容如下:
这是一个简单的测试用的文本文件
这是第二行了
笑嘻嘻地敲下第三行,我觉得差不多了
3
1
这是一个简单的测试用的文本文件
2
这是第二行了
3
笑嘻嘻地敲下第三行,我觉得差不多了
我们要读取该文件内容并同样复写到另一个文件temp.txt中,则代码为:
public static void main(String[] args) {
//创建副本
File temp = new File("C:\Users\Dulk\Desktop\temp.txt");
if (!temp.exists()) {
try {
temp.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
//读取源文件
File file = new File("C:\Users\Dulk\Desktop\test.txt");
if (file.exists()) {
FileReader reader = null;
BufferedReader bufferedReader = null;
FileWriter writer = null;
BufferedWriter bufferedWriter = null;
try {
reader = new FileReader(file);
bufferedReader = new BufferedReader(reader);
writer = new FileWriter(temp);
bufferedWriter = new BufferedWriter(writer);
String line = bufferedReader.readLine();
while (line != null) {
System.out.println(line);
//数据写入
bufferedWriter.write(line + "
");
line = bufferedReader.readLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufferedWriter != null) {
//刷新和关闭
bufferedWriter.flush();
bufferedWriter.close();
}
if (bufferedReader != null) {
bufferedReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
x
1
public static void main(String[] args) {
2
3
//创建副本
4
File temp = new File("C:\Users\Dulk\Desktop\temp.txt");
5
if (!temp.exists()) {
6
try {
7
temp.createNewFile();
8
} catch (IOException e) {
9
e.printStackTrace();
10
}
11
}
12
13
//读取源文件
14
File file = new File("C:\Users\Dulk\Desktop\test.txt");
15
if (file.exists()) {
16
FileReader reader = null;
17
BufferedReader bufferedReader = null;
18
FileWriter writer = null;
19
BufferedWriter bufferedWriter = null;
20
21
try {
22
reader = new FileReader(file);
23
bufferedReader = new BufferedReader(reader);
24
25
writer = new FileWriter(temp);
26
bufferedWriter = new BufferedWriter(writer);
27
28
String line = bufferedReader.readLine();
29
while (line != null) {
30
System.out.println(line);
31
//数据写入
32
bufferedWriter.write(line + "
");
33
line = bufferedReader.readLine();
34
}
35
36
} catch (IOException e) {
37
e.printStackTrace();
38
} finally {
39
try {
40
if (bufferedWriter != null) {
41
//刷新和关闭
42
bufferedWriter.flush();
43
bufferedWriter.close();
44
}
45
if (bufferedReader != null) {
46
bufferedReader.close();
47
}
48
} catch (IOException e) {
49
e.printStackTrace();
50
}
51
52
}
53
}
54
55
}
3.2 注意事项
- read方法每执行一次会移动文件指针,文件末尾时返回-1,不要将read方法直接放在循环中作为判断避免多次移动指针
- 在new一个FileWriter时,也可以增加一个参数true,表示不覆盖只是增加内容,如 new FileWriter(file, true);
- 写入文本中换行有两种方式,第一种调用newLine方法新建空行;第二种在增加转义字符,win中使用 " ",linux下使用 " "