Java 入门指南:Java IO流 —— 转换流、扫描流、打印流
转换流
转换流可以将一个 字节流 包装成 字符流,或者将一个字符流包装成字节流。这种转换通常用于处理文本数据,如读取文本文件或将数据从网络传输到应用程序。
转换流主要有两种类型:InputStreamReader 和 OutputStreamWriter。
InputStreamReader 将一个字节输入流转换为一个字符输入流,而 OutputStreamWriter 将一个字节输出流转换为一个字符输出流。它们使用指定的字符集将字节流和字符流之间进行转换。常用的字符集包括 UTF-8、GBK、ISO-8859-1 等。
![![[转换流.png]]](https://i-blog.csdnimg.cn/direct/5cb6aa20c3be42dea86b9a015d0346d7.png)
为提高读写效率,会在转换流上添加一层缓冲流
在使用转换流时,需要指定正确的字符集编码方式,否则可能会导致数据读取或写入出现乱码。
InputStreamReader
java.io.InputStreamReader 是 Reader 类的子类。它的作用是将字节流(InputStream)转换为字符流(Reader),同时支持指定的字符集编码方式,从而实现字符流与字节流之间的转换。
构造方法
-
InputStreamReader(InputStream in): 创建一个使用默认字符集的字符流。 -
InputStreamReader(InputStream in, String charsetName): 创建一个指定字符集(ASCII、Unicode、GBK…)的字符流。
常用方法
InputStreamReader 类的常用方法包括:
-
read():从输入流中读取一个字符的数据。 -
read(char[] cbuf, int off, int len):从输入流中读取 len 个字符的数据到指定的字符数组 cbuf 中,从 off 位置开始存放。 -
ready():返回此流是否已准备好读取。 -
close():关闭输入流。
使用示例
假设有一个字节流 InputStream,需要将其转换为字符流进行读取。
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;public class InputStreamReaderExample {public static void main(String[] args) {// 假设有一个字节流 InputStreamInputStream inputStream = getClass().getResourceAsStream("/example.txt");try (InputStreamReader isr = new InputStreamReader(inputStream);BufferedReader br = new BufferedReader(isr)) {String line;while ((line = br.readLine()) != null) {System.out.println(line);}} catch (IOException e) {e.printStackTrace();}}
}
示例说明
-
创建
InputStream:这里使用getClass().getResourceAsStream()方法来获取资源文件example.txt的InputStream。 -
创建
InputStreamReader:使用inputStream创建一个InputStreamReader,默认使用系统默认的字符集。 -
创建
BufferedReader:使用InputStreamReader创建一个BufferedReader,以便逐行读取数据。 -
读取数据:通过
BufferedReader的readLine()方法逐行读取数据,并打印出来。
如果想要指定字符集编码,可以在创建 InputStreamReader 时传递编码名称:
InputStreamReader isr = new InputStreamReader(inputStream, "UTF-8");
OutputStreamWriter
java.io.OutputStreamWriter 是 Writer 的子类,字面看容易误以为是转为字符流,其实是将字符流转换为字节流,是字符流到字节流的桥梁。
构造方法
-
OutputStreamWriter(OutputStream in): 创建一个使用默认字符集的字符流。 -
OutputStreamWriter(OutputStream in, String charsetName):创建一个指定字符集的字符流。
常用方法
-
write(int c):向输出流中写入一个字符的数据。 -
write(char[] cbuf, int off, int len):向输出流中写入指定字符数组 cbuf 中的 len 个字符,从 off 位置开始。 -
flush():将缓冲区的数据写入输出流中。 -
close():关闭输出流。
使用示例
假设要将字符数据写入一个字节流 OutputStream 中
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.BufferedWriter;
import java.io.IOException;public class OutputStreamWriterExample {public static void main(String[] args) {// 假设有一个字节流 OutputStreamOutputStream outputStream = System.out; // 这里使用标准输出流try (OutputStreamWriter osw = new OutputStreamWriter(outputStream, "UTF-8");BufferedWriter bw = new BufferedWriter(osw)) {String content = "Hello, World!";bw.write(content);bw.newLine(); // 写入换行符bw.flush(); // 确保所有数据都被写入} catch (IOException e) {e.printStackTrace();}}
}
示例说明:
-
创建
OutputStream:这里使用标准输出流System.out作为OutputStream。 -
创建
OutputStreamWriter:使用outputStream创建一个OutputStreamWriter,并指定字符集为"UTF-8"。 -
创建
BufferedWriter:使用OutputStreamWriter创建一个BufferedWriter,以便高效地写入数据。 -
写入数据:通过
BufferedWriter的write()方法写入字符串content。 -
换行:使用
newLine()方法写入换行符。 -
刷新:使用
flush()方法确保所有数据都被写入。
使用转换流进行文件读写
假设有一个文本文件 input.txt,需要读取该文件的内容,并将内容写入另一个文件 output.txt。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;public class FileReadWriteExample {public static void main(String[] args) {String inputFilePath = "input.txt";String outputFilePath = "output.txt";try (InputStreamReader isr = new InputStreamReader(new FileInputStream(inputFilePath), "UTF-8");BufferedReader br = new BufferedReader(isr);OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(outputFilePath), "UTF-8");BufferedWriter bw = new BufferedWriter(osw)) {String line;while ((line = br.readLine()) != null) {bw.write(line);bw.newLine();bw.flush();}} catch (IOException e) {e.printStackTrace();}}
}
示例说明:
-
创建
InputStreamReader:使用FileInputStream创建一个InputStreamReader,并指定字符集为"UTF-8"。 -
创建
BufferedReader:使用InputStreamReader创建一个BufferedReader,以便逐行读取数据。 -
创建
OutputStreamWriter:使用FileOutputStream创建一个OutputStreamWriter,并指定字符集为"UTF-8"。 -
创建
BufferedWriter:使用OutputStreamWriter创建一个BufferedWriter,以便高效地写入数据。 -
读取和写入数据:通过
BufferedReader的readLine()方法逐行读取数据,并通过BufferedWriter的write()方法写入数据。 -
换行:使用
newLine()方法写入换行符。 -
刷新:使用
flush()方法确保所有数据都被写入。
扫描流
扫描流 Scanner 是 java.util.Scanner 中的一个类,它可以用来从标准输入、文件、字符串等多种来源中获取输入。使用 Scanner 类能够方便、快速地从输入流中读取数据。
Scanner 类还提供了许多其他方法,例如 nextInt()、nextDouble() 等,用于读取不同数据类型的输入。
构造方法
Java 中 java.util.Scanner 类提供了多个构造方法,用于创建不同类型的 Scanner 对象。
Scanner(File source):创建一个从指定文件中读取数据的Scanner对象。
File file = new File("input.txt");
Scanner scanner = new Scanner(file);
Scanner(InputStream source):创建一个从指定输入流中读取数据的 Scanner 对象。
InputStream inputStream = System.in;
Scanner scanner = new Scanner(inputStream);
Scanner(String source):创建一个从指定字符串中读取数据的 Scanner 对象。
String text = "Hello, world!";
Scanner scanner = new Scanner(text);
Scanner(File source, String charsetName):创建一个从指定文件使用指定字符集编码中读取数据的 Scanner 对象。
File file = new File("input.txt");
Scanner scanner = new Scanner(file, "UTF-8");
Scanner(InputStream source, String charsetName):创建一个从指定输入流使用指定字符集编码中读取数据的 Scanner 对象。
InputStream inputStream = System.in;
Scanner scanner = new Scanner(inputStream, "UTF-8");
上述构造方法中的 source 参数均为输入源,charsetName 参数用于指定字符集编码(可选参数)。
System.in
System.in 是 Java 标准库中的一个静态字段,它是 java.io.InputStream 类型的对象,用于表示标准输入流。在控制台应用程序中,System.in 表示标准输入(键盘输入)。
可以通过创建 Scanner 对象,并将 System.in 作为参数传递给 Scanner 构造方法,使用 Scanner 对象读取从键盘输入的数据。
Scanner scan = new Scanner(System.in);
String string = scan.nextline();
int age = scan.nextInt();
scan.close();
打印流
System.out 实际是用于获取一个 PrintStream 对象,print方法实际调用的是 PrintStream 对象的 write 方法。
PrintStream 属于字节打印流,与之对应的孪生兄弟是 PrintWriter (字符打印流)。PrintStream 是 OutputStream 的子类,PrintWriter 是 Writer 的子类。
打印流具有以下几个特点:
-
可以自动进行数据类型转换:打印流可以将各种数据类型转换为字符串,并输出到指定的输出流中。
-
可以自动进行换行操作:打印流可以在输出字符串的末尾自动添加换行符,方便输出多个字符串时的格式控制。
-
可以输出到控制台或者文件中:打印流可以将数据输出到控制台或者文件中,方便调试和日志记录(生产环境下更推荐使用 Logback、ELK 等)。
PrintStream 类的常用方法包括:
-
print():输出一个对象的字符串表示形式。 -
println():输出一个对象的字符串表示形式,并在末尾添加一个换行符。 -
printf():使用指定的格式字符串和参数输出格式化的字符串。
Java 的常用转换说明符
| 转换符 | 说明 |
|---|---|
| %d or %i | 输出一个十进制整数。 |
| %s | 输出一个字符串。 |
| %x or %X | 输出一个十六进制整数,%x 输出小写字母,%X 输出大写字母。 |
| %f or %F | 输出一个浮点数。 |
| %e or %E | 输出一个科学计数法表示的浮点数,%e 输出小写字母 e,%E 输出大写字母 E。 |
| %g or %G | 输出一个浮点数,自动选择 %f 或 %e/%E 格式输出。 |
| %c | 输出一个字符。 |
| %b | 输出一个布尔值。 |
| %h | 输出一个哈希码(16进制)。 |
| %n | 换行符。 |
Java printf 支持的修饰符
Java 的 printf 方法还支持一些修饰符,用于指定输出的宽度、精度、对齐方式等(类似C、C++)。
-
宽度修饰符:用数字指定输出的最小宽度,如果输出的数据不足指定宽度,则在左侧或右侧填充空格或零。
-
精度修饰符:用点号(.)和数字指定浮点数或字符串的精度,对于浮点数,指定小数点后的位数,对于字符串,指定输出的字符数。
-
对齐修饰符:用减号(-)或零号(0)指定输出的对齐方式,减号表示左对齐,零号表示右对齐并填充零。
