转换流
转换流可以将一个 字节流 包装成 字符流,或者将一个字符流包装成字节流。这种转换通常用于处理文本数据,如读取文本文件或将数据从网络传输到应用程序。
转换流主要有两种类型:InputStreamReader
和 OutputStreamWriter
。
InputStreamReader
将一个字节输入流转换为一个字符输入流,而 OutputStreamWriter
将一个字节输出流转换为一个字符输出流。它们使用指定的字符集将字节流和字符流之间进行转换。常用的字符集包括 UTF-8、GBK、ISO-8859-1 等。
为提高读写效率,会在转换流上添加一层缓冲流
在使用转换流时,需要指定正确的字符集编码方式,否则可能会导致数据读取或写入出现乱码。
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) {
// 假设有一个字节流 InputStream
InputStream 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) {
// 假设有一个字节流 OutputStream
OutputStream 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)指定输出的对齐方式,减号表示左对齐,零号表示右对齐并填充零。