Java基础:IO流之字符流

字节流

Java 中的 IO 流按操作数据可以分为字节流与字符流,字节流主要用于对图片,视频等数据进行操作。而字符流是可以直接读写字符的 IO 流,对文本文件可以进行较为方便的操作。

字节输出流

字符流中的输出流的基类是 Writer,但是该方法是抽象的,只能使用创建其子类对象。

由于最常用的操作是文件,所以这里我们选择 FileWrite 来演示。

写入字符到指定文本文件中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.io.*;

public class FileWriteDemo {
public static void main(String[] args) throws IOException {
//这里会抛出异常,因为创建文件输出流对象时,可能指定了一个不存在的路径,那么就无法继续操作了,这里我们直接将异常抛出。
//如若该文件不存在,则会创建,已存在则会将其覆盖。
FileWriter fw = new FileWriter("F:\\demo.txt");

//调用 write 方法,会将数据存入到流中,而不是直接写入到文件。
fw.write("abc");

//刷新流对象中的缓冲中的数据,将数据存入到文件中。
fw.flush();

//再次写入数据到流中
fw.write("xyz");

//关闭输出流,关闭前会将缓冲中的数据写入到文件中,也就是再 flush 一次
fw.close();

//注意:当调用 close 方法关闭流之后,将无法再向流中写入数据。
fw.write("qwer");

}
}

要点:

  • new FileWrite("F:\\demo.txt"); 会将文件覆盖,如想对文件进行追加操作,则使用另一个构造方法 new FileWrite("F:\\demo.txt", true) 即可将数据写入文件末尾处,而不是写入文件开始处。
  • write 方法是将数据写入到流中,而不是文件中。
  • flush 方法会将流中的数据写入到文件
  • close 方法会将流中的数据写入到文件中,然后会关闭流,不可在对流进行操作。
  • Windows 环境下写入回车符的方法:fw.write("\r\n");

字符流异常的处理方式

在上述的例子中,我们直接将 IO 异常抛出了,这里我们演示下如何正确处理 IO 异常。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.io.*;

public class FileWriteDemo {
public static void main(String[] args) {
FileWriter fw = null;

try {
//如果文件已存在,则在文件最后进行追加,不存在,则创建文件
fw = new FileWriter("F:\\demo.txt", true);

fw.write("abc");

fw.flush();

fw.write("xyz");
} catch (IOException e) {
throw new RuntimeException("读写失败");
} finally {
try {
if (fw != null)
fw.close();
} catch (IOException e) {

}
}

}
}

这里要注意的是:在 finally 中对流资源进行关闭时,要注意关闭动作本身也会抛出异常,要记得处理。

字节输入流

字符流中的输出流的基类是 Reader,但是该方法是抽象的,只能使用创建其子类对象。

由于最常用的操作是文件,所以这里我们选择 FileReader 来演示。

从一个文件中读取文本内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.io.FileReader;
import java.io.IOException;

public class FileReadDemo2 {
public static void main(String[] args) throws IOException {
//创建一个文件输入流,同样这里也会抛出异常,为了代码简洁这里就直接抛出了
//有关异常的处理请参照上方的输出流中的异常处理方式。
FileReader fr = new FileReader("F:\\demo.txt");

//读取一个字符,返回值是字符对于的 ASCII 编码中的数值。所以查看时要将其转为 char 类型。
int ch1 = fr.read();
System.out.println((char)ch1);

char[] ch = new char[1024];

int num = 0;

//将读取到的内容存储到字符数组中,返回值是读取的有效字符的个数。
//当读取到文件末尾,会返回 -1
while ((num = fr.read(ch)) != -1) {
//为了避免资源的浪费,所以只取有效数据,num 即为有效数据的个数。
System.out.print(new String(ch, 0, num));
}

}
}

要点:

  • fr.read() 返回的是一个字符在 ASCII 编码中的数值
  • fr.read(char[] ch) 返回的是存入指定数组中有效数据的个数

综合练习

拷贝文本文件

拷贝文本文件其实就是将一个文件读取后,在将其内容写入到另一个文件中。所以将上方我们的示例综合起来即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyTextFile {
public static void main(String[] args) {
FileReader fr = null;
FileWriter fw = null;

try {

fr = new FileReader("F:\\demo.txt");
fw = new FileWriter("F:\\demoCopy.txt");
char[] ch = new char[1024];

int num = 0;
while ((num = fr.read(ch)) != -1) {
fw.write(ch, 0, num);
fw.flush();
}

} catch (IOException e) {
throw new RuntimeException("拷贝失败");
} finally {
try {
if (fw != null)
fw.close();
if (fr != null)
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}