Java 的 PrintStream 类(即 java.io.PrintStream)能够让你将格式化的数据写入底层的 OutputStream。该类具备将 int、long 等基本数据类型转化为文本形式的能力,而非直接处理它们的字节值。这也正是它被命名为 PrintStream 的缘由,它会把原始数据转化为文本,就如同信息被打印到屏幕上(或是打印在纸张上)时呈现的样子。
以下是一个简单的 PrintStream 示例:
package com.hxstrive.java_io;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintStream;
public class PrintStreamExample {
public static void main(String[] args) throws IOException {
// 写出数据
try(PrintStream ps = new PrintStream("test.txt")){
ps.println("Hello, Java!");
ps.println((int)1024);
ps.println(true);
ps.println(3.1415d);
}
// 读取数据
try(BufferedInputStream in = new BufferedInputStream(new FileInputStream("test.txt"))) {
byte[] buffer = new byte[1024];
int len = in.read(buffer);
System.out.println(new String(buffer, 0, len));
}
}
}运行输出:
Hello, Java! 1024 true 3.1415
上述示例,首先创建了一个连接到 OutputStream 的 PrintStream。其次,向 PrintStream 打印几个原始值,写入到 test.txt 文件。最后,通过 BufferedInputStream 读取 test.txt 文件的内容。
你或许对 Java 里两个广为人知的 PrintStream 实例并不陌生,它们就是 System.out 和 System.err。倘若你曾使用过这两个流中的任意一个,那实际上你就已经用过 PrintStream 了。
在 Java 中,PrintStream 类提供了功能强大的 format() 和 printf() 方法。这两个方法的功能是完全一致的,不过对于熟悉 C 语言的程序员而言,“printf” 这个名称会让他们感觉更为亲切。借助这些方法,你能够运用格式化字符串,以一种十分高级的方式将文本和数据进行融合。
示例:
package com.hxstrive.java_io;
import java.io.PrintStream;
public class PrintStreamPrintfExample {
public static void main(String[] args) {
// 定义一些不同类型的变量,用于后续格式化输出
String name = "Alice";
int age = 25;
double height = 1.65;
boolean isStudent = true;
try(PrintStream ps = System.out) {
// 输出基本信息,使用 %s 格式化字符串,%d 格式化整数
ps.printf("姓名: %s,年龄: %d 岁\n", name, age);
// 输出带有小数的信息,使用 %.2f 格式化双精度浮点数,保留两位小数
ps.printf("姓名: %s,身高: %.2f 米\n", name, height);
// 输出布尔值信息,使用 %b 格式化布尔值
ps.printf("姓名: %s,是否为学生: %b\n", name, isStudent);
// 格式化输出带宽度的字符串,%-10s 表示左对齐,宽度为 10
ps.printf("|%-10s|%10s|\n", "姓名", "年龄");
ps.printf("|%-10s|%10d|\n", name, age);
// 格式化输出日期信息,使用 %tF 格式化日期为 yyyy-MM-dd 格式
java.util.Date currentDate = new java.util.Date();
ps.printf("当前日期: %tF\n", currentDate);
// 格式化输出时间信息,使用 %tT 格式化时间为 HH:mm:ss 格式
ps.printf("当前时间: %tT\n", currentDate);
// 格式化输出带有前导零的整数,使用 %03d 表示宽度为 3,不足用 0 补齐
int number = 7;
ps.printf("带有前导零的数字: %03d\n", number);
}
}
}运行输出:
姓名: Alice,年龄: 25 岁 姓名: Alice,身高: 1.65 米 姓名: Alice,是否为学生: true |姓名 | 年龄| |Alice | 25| 当前日期: 2025-04-07 当前时间: 14:57:38 带有前导零的数字: 007
PrintStream 类中的 format() 方法用于将格式化的字符串写入此输出流。它允许你使用格式化说明符来控制输出的格式,支持多种数据类型的格式化输出,例如整数、浮点数、字符串、日期等。
该方法有两个重载版本:
public PrintStream format(String format, Object... args):使用指定的格式字符串和参数生成格式化的输出。
public PrintStream format(Locale l, String format, Object... args):使用指定的语言环境、格式字符串和参数生成格式化的输出。
示例:
package com.hxstrive.java_io;
import java.io.PrintStream;
import java.util.Date;
public class PrintStreamFormatExample {
public static void main(String[] args) {
// 定义一些变量用于格式化输出
String name = "John";
int age = 30;
double salary = 5000.50;
Date currentDate = new Date();
try(PrintStream ps = System.out) {
// 示例 1:格式化输出字符串和整数
// %s 用于格式化字符串,%d 用于格式化十进制整数
ps.format("姓名: %s,年龄: %d\n", name, age);
// 示例 2:格式化输出浮点数,保留两位小数
// %.2f 表示格式化浮点数,保留两位小数
ps.format("姓名: %s,薪水: %.2f\n", name, salary);
// 示例 3:格式化输出日期
// %tF 用于格式化日期为 yyyy-MM-dd 格式
ps.format("当前日期: %tF\n", currentDate);
// 示例 4:格式化输出带宽度和对齐的字符串
// %-10s 表示左对齐,宽度为 10 的字符串格式化
ps.format("|%-10s|%10d|\n", "姓名", age);
ps.format("|%-10s|%10.2f|\n", name, salary);
}
}
}运行结果:
姓名: John,年龄: 30 姓名: John,薪水: 5000.50 当前日期: 2025-04-07 |姓名 | 30| |John | 5000.50|
注意,format() 方法里,格式化字符串是由普通字符和格式说明符构成的。格式说明符以 % 开头,用于指定如何格式化相应的参数。以下是常见的格式说明符及其作用:
格式说明符 | 说明 | 示例 |
%b、%B | 用于格式化布尔类型的值。%b输出小写形式,%B输出大写形式。 | System.out.format("%b", true); 输出 true |
%s、%S | 用于格式化字符串类型的值。%s输出小写形式(若适用),%S输出大写形式(若适用)。 | System.out.format("%s", "hello"); 输出 hello |
%c、%C | 用于格式化字符类型的值。%c输出小写形式,%C输出大写形式。 | System.out.format("%c", 'A'); 输出 A |
整数类型
格式说明符 | 说明 | 示例 |
%d | 用于格式化十进制整数。 | System.out.format("%d", 123); 输出 123 |
%o | 用于格式化八进制整数。 | System.out.format("%o", 123); 输出 173 |
%x、%X | 用于格式化十六进制整数。%x输出小写字母,%X输出大写字母。 | System.out.format("%x", 255); 输出 ff |
浮点类型
格式说明符 | 说明 | 示例 |
%f | 用于格式化十进制浮点数。默认保留 6 位小数。 | System.out.format("%f", 3.14159); 输出 3.141590 |
%e、%E | 用于格式化科学计数法表示的浮点数。%e输出小写 e,%E输出大写 E。 | System.out.format("%e", 1234.56); 输出 1.234560e+03 |
%g、%G | 根据数值大小自动选择 %f或 %e格式。%g输出小写形式,%G输出大写形式。 | System.out.format("%g", 1234.56); 输出 1234.56 |
格式说明符 | 说明 | 示例 |
%t | 这是日期和时间格式化的前缀,后面需要跟具体的日期时间转换字符。 | |
%tY | 输出年份,4 位数字。 | System.out.format("%tY", new java.util.Date()); 输出如 2024 |
%ty | 输出年份的后两位数字。 | System.out.format("%ty", new java.util.Date()); 输出如 24 |
%tm | 输出月份,两位数字(01 - 12)。 | System.out.format("%tm", new java.util.Date()); 输出如 04 |
%td | 输出日期,两位数字(01 - 31)。 | System.out.format("%td", new java.util.Date()); 输出如 07 |
%tH | 输出 24 小时制的小时数,两位数字(00 - 23)。 | System.out.format("%tH", new java.util.Date()); 输出如 14 |
%tM | 输出分钟数,两位数字(00 - 59)。 | System.out.format("%tM", new java.util.Date()); 输出如 30 |
%tS | 输出秒数,两位数字(00 - 60)。 | System.out.format("%tS", new java.util.Date()); 输出如 45 |
%tF | 等价于 %tY-%tm-%td,输出 yyyy-MM-dd格式的日期。 | System.out.format("%tF", new java.util.Date()); 输出如 2024-04-07 |
%tT | 等价于 %tH:%tM:%tS,输出 HH:mm:ss格式的时间。 | System.out.format("%tT", new java.util.Date()); 输出如 14:30:45 |
格式说明符 | 说明 | 示例 |
%% | 输出一个 %字符。 | System.out.format("比例: 50%%"); 输出 比例: 50% |
%n | 输出平台特定的换行符。 | System.out.format("第一行%n第二行"); 输出换行后的两行内容 |
除了基本的格式说明符,还可以使用修饰符来进一步控制输出格式,常见修饰符如下:
宽度:在 % 后指定一个正整数,表示输出的最小宽度。例如 %5d 表示输出的整数至少占 5 个字符宽度。
精度:对于浮点数,在宽度后加 . 和数字表示保留的小数位数,如 %.2f 表示保留两位小数。
对齐:- 表示左对齐,例如 %-10s 表示左对齐且宽度为 10 的字符串输出。
正负号:+ 表示输出正负号,例如 %+d 会为正数也加上 + 号。
前导零:0 表示用 0 填充宽度,例如 %05d 会在不足 5 位的整数前补 0。
当你完成向 PrintStream 写入数据的操作后,请务必记得将其关闭。需要注意的是,关闭 PrintStream 时,它所写入的 OutputStream 实例也会随之关闭。
若要关闭 PrintStream,只需调用其 close() 方法即可。例如:
printStream.close();
您还可以使用 Java 7 中引入的 try-with-resources 结构。例如
OutputStream output = new FileOutputStream("data.bin");
try(PrintStream printStream = new PrintStream(output)){
printStream.writeInt(123);
//...
}需留意,此处不再有任何显式的 close() 方法调用,因为 try-with-resources 结构已自动处理了资源关闭问题。
另外,首个 FileOutputStream 实例并非在 try-with-resources 代码块中创建,这表明 try-with-resources 块不会自动关闭该 FileOutputStream 实例。不过,当 PrintStream 关闭时,它会同时关闭其写入数据的 OutputStream 实例,所以 FileOutputStream 实例会在 PrintStream 关闭时一并关闭。