0%

IO之字符流

1. 总体结构

在这里插入图片描述
由于字节流操作中文不是特别方便,所以,java就提供了转换流。其中字符流就是字节流+编码表。字符流的两个顶层父类为Reader和Writer,分别用于字符流的读取和写入。下面分别来简单地介绍这些流的用法。

2. InputStreamReader与OutputStreamWriter

2.1 使用时机

  1. 源或者目的对应的设备是字节流,但是操作的却是文本数据的时候可以使用转换流作为桥梁,以提高对文本操作的便捷;
  2. 一旦操作的文本涉及到具体的指定编码表时,必须使用转换流

    2.2 InputStreamReader 字符输入流

    该类为转换流,实现了根据指定编码将字节数据到字符数据的转换(解码)。

构造方法
在这里插入图片描述
下面演示一下InputStreamReader的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//1.构建要读取的文件对象
File srcFile = new File("f:/demo.txt");
//2.建立输入流
InputStream fis = new FileInputStream(srcFile);
//3.按指定编码将字节数据转换为字符输入流
InputStreamReader isr = new InputStreamReader(fis, "Unicode");
//4.建立缓存区
char[] buf = new char[1024];
int num = 0; //读到的字符数
//5.输出数据
while((num = isr.read(buf))!= -1) {
System.out.print(new String(buf, 0, num));
}//输出 演示InputStreamReader类
//6.关闭流
isr.close();
fis.close();

我在本地f盘下的demo.txt文件以Unicode编码来保存文件数据,如下示:
在这里插入图片描述
所以在InputStreamReader来读取该文件的数据时,必须以相同的编码Unicode去读取数据,即解码。否则会发生乱码的情况。

2.3 OutputStreamWriter 字符输出流

该类为转换流,实现了根据指定编码将字符数据到字节数据的转换(编码)
构造方法
在这里插入图片描述
下面演示一下OutputStreamWriter的使用(实现文件的复制):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//1.构建文件对象
File srcFile = new File("src/io/demo.txt");
File desFile = new File("src/io/desFile.txt");
//2.建立输入输出字节流
InputStream fis = new FileInputStream(srcFile);
OutputStream fos = new FileOutputStream(desFile);
//3.按指定编码将字节数据转换为字符输入输出流
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
//4.建立缓冲区
char[] buf = new char[1024];
int num = 0;
//5.读取指定文件的数据并写入到指定文件之中
while((num = isr.read(buf)) != -1) {
osw.write(buf, 0, num);
osw.flush();//刷新流
}
//6.关闭流
osw.close();
isr.close();
fos.close();
fis.close();

3. BufferedReader与BufferedWriter

这两个类为字符缓冲流,在普通Reader或Writer的基础上,提供了缓冲功能,可以更加高效的读取和写入数据;

3.1 BufferedReader

3.1.1 构造方法

在这里插入图片描述

3.1.2 常用方法

  1. public int read() throws IOException

    读取单个字符。,如果已到达流末尾,则返回 -1

  2. public int read(char[] cbuf) throws IOException

    一次读取一个字节数组,读取的字符数,如果已到达流的末尾,则返回 -1

    3.1.2.1 特有方法
  3. public String readLine() throws IOException

    读取一个文本行。通过下列字符之一即可认为某行已终止:换行 (‘\n’)、回车 (‘\r’) 或回车后直接跟着换行。读取返回的字符串包含该行内容,不包含任何行终止符,如果已到达流末尾,则返回 null

    3.1.2.2 基本用法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    InputStreamReader isr = null;
    BufferedReader br = null;
    try {
    try {
    //1.构建字符读取流对象
    isr = new InputStreamReader(new FileInputStream("src/io/demo.txt"));
    //2.包装成字符缓冲读取流
    br = new BufferedReader(isr);
    //3.一次去读一行数据
    String content = null;
    while((content = br.readLine())!=null) {
    //4.直接输出数据
    System.out.println(content);
    }

    } finally {
    //6.关闭包装流,其实关闭的就是被缓冲的流对象isr
    br.close();
    }
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }

3.2 BufferedWriter

3.2.1 构造方法

在这里插入图片描述

3.2.2 常用方法

在这里插入图片描述
注意:不同的操作系统有些换行符号是不一样的,比如Windows的换行符是’\r\n’,而有的是’\n’。为了是代码的复用性和移植性更好,可以使用BufferedWriter的特有方法newLine写入一个换行符。

3.2.2.1 基本用法

下面实现在控制台输入一行数据后直接输出打印在控制台上。

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
InputStream in = null;
InputStreamReader isr = null;
BufferedReader bufr = null;
OutputStream out = null;
OutputStreamWriter osw = null;
BufferedWriter bufw = null;

try {//复杂捕获异常
try {//复杂关闭流
//1.创建从控制台来的字节输入流
in = System.in;
//2.将字节输入流转换为字符输入流
isr = new InputStreamReader(in);
//3.对字符流进行高效装饰,即加缓冲区
bufr = new BufferedReader(isr);
//4.读取一行数据
String line = bufr.readLine();

//5.创建输出到控制台的字节输出流
out = System.out;
//6.将字节输出流转换为字符输出流
osw = new OutputStreamWriter(out);
//7.对对字符流进行高效装饰,即加缓冲区
bufw = new BufferedWriter(osw);
//8.写入一行数据
bufw.write(line);
bufw.flush();//刷新
} finally {
//9.仅关闭流包装流就可以了,其他的流对象也会被关闭
bufw.close();
bufr.close();
}
} catch (IOException e) {
e.printStackTrace();
}

运行结果:
在这里插入图片描述

4. FileReader与FileWriter

4.1 FileReader

FileReader类从InputStreamReader类继承而来。该类按字符读取流中数据。其是用来方便的从文件中读出字符的类,带有默认编码和默认缓冲区大小。如果要改变默认编码和默认缓冲区大小可以用FileInputStream来构造InputStreamReader来实现。

4.1.1 构造方法

在这里插入图片描述

4.1.2 常用方法

在这里插入图片描述

4.1.2.1 基本用法

下面演示下读取一个文本文件,然后将读取到的字符打印在控制台上。

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

public class FileReaderDemo {
public static void main(String[] args) throws IOException {
//1.构建要读取的文件对象
File srcFile = new File("src/io/demo.txt");
//2.建立字符读取流
FileReader fr = new FileReader(srcFile);
//3.读取数据
char[] buf = new char[1024]; //缓冲区
int num = 0; //读取到的字符数
//一次读取一个字节数组的数据,如果流已到达末尾则返回-1
while((num = fr.read(buf))!= -1) {
//4.直接输出数据
System.out.println(new String(buf, 0, num));
}
//5.关闭流
fr.close();
}
}

4.2 FileWriter

FileWriter 类从 OutputStreamWriter 类继承而来。该类按字符向流中写入数据。这个类默认带有字符编码方式和缓冲区大小,如果要改变指定编码和缓冲区大小可以用FileOutputStream来构造一个OutputStreamWriter来实现。

4.2.1 构造方法

在这里插入图片描述

4.2.2 常用方法

方法说明
public void write(int c)
写入当个字符c。
public void write(char[] c, int offset, int len)
写入字符数组中开始为offset长度为len的某一部分。
public void write(String s, int offset, int len)
写入字符串中开始为offset长度为len的某一部分。
public void flush()
刷新流,将数据直接写入目的地中
4.2.2.1基本用法

下面实现文件的复制

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
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class FileWriterDemo {
public static void main(String[] args) throws IOException {
//1.构建文件字符输入流
FileReader fr = new FileReader(new File("src/io/demo.txt"));
//2.缓冲流包装
BufferedReader bufr = new BufferedReader(fr);
//3.构建文件字符输出流,第二个参数为true实现数据追加
FileWriter fw = new FileWriter(new File("src/io/desFile.txt"),false);
//4.缓冲流包装
BufferedWriter bufw = new BufferedWriter(fw);
//5.读取一行数据
String content = null;
while((content = bufr.readLine())!=null) {
//6.写入一行数据
bufw.write(content);
bufw.newLine();//加一个换行符
//7.刷新缓冲区
bufw.flush();
}
//7.关闭流
bufw.close();
bufr.close();
}
}

5. LineNumberReader

跟踪行号的缓冲字符输入流

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
package io;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;

public class LineNumberReaderDemo {
public static void main(String[] args) {
LineNumberReader lnr = null;
try {
try {
//1.构建字符读取流
FileReader fr = new FileReader(new File("src/io/demo.txt"));
//2.构建跟踪行号的缓冲字符输出流
lnr = new LineNumberReader(fr);
//3.读取数据并输出当前行号
lnr.setLineNumber(2);//设置当前行号为2,默认为0
String line;
while ((line=lnr.readLine()) != null) {
System.out.println(lnr.getLineNumber()+":"+line);
}

} finally {
//4.关闭流
lnr.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

其中demo.txt的内容如下:
在这里插入图片描述
运行结果:

1
2
3
3:演示LineNumberReader类演示LineNumberReader类
4:演示LineNumberReader类 演示LineNumberReader类
5:演示LineNumberReader类

注意:setLineNumber()能改变行号,却不能改变读的位置

6. PrintWriter

该类用于向文本输出流打印对象的格式化表示形式。此类实现在 PrintStream 中的所有 print 方法,且此类中的方法不会抛出 I/O 异常。

6.1 构造方法

PrintWriter(File file)
使用指定文件创建不具有自动行刷新的新 PrintWriter。
PrintWriter(File file, String csn)
创建具有指定文件和字符集且不带自动刷行新的新 PrintWriter。
PrintWriter(OutputStream out)
根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。
PrintWriter(OutputStream out, boolean autoFlush)
通过现有的 OutputStream 创建新的 PrintWriter。
PrintWriter(String fileName)
创建具有指定文件名称且不带自动行刷新的新 PrintWriter。
PrintWriter(String fileName, String csn)
创建具有指定文件名称和字符集且不带自动行刷新的新 PrintWriter。
PrintWriter(Writer out)
创建不带自动行刷新的新 PrintWriter。
PrintWriter(Writer out, boolean autoFlush)
创建带自动行刷新的新 PrintWriter。

6.2 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
FileWriter fw = null;
PrintWriter pw = null;
try {
try {
//1.构建字符打印流
fw = new FileWriter(new File("src/io/desFile.txt"));
pw = new PrintWriter(fw, true);
//2.向指定文件写入内容
String content1 = "这是写入到desFile.txt中的数据内容";
String content2 = "这是补充的内容";
pw.println(content1);
pw.println(content2);
pw.flush();//刷新
} finally {
//2.关闭流
pw.close();
fw.close();
}
} catch (IOException e) {
e.printStackTrace();
}

运行结果:
在这里插入图片描述

------ 本文结束------