假设我们需要验证以下方法。
/**
* Prints {@code hello, world}, to the {@link System#out}, followed by a system dependent line separator.
*
* @param args command line arguments.
*/
public static void main(String... args) {
System.out.printf("hello, world%n"); // %n !!!!!!
}
现在我们可以验证该方法是否打印了
hello, world
。
/**
* Verifies that the {@link HelloWorld#main(String...)} method prints {@code hello, world}, to the
* {@link System#out}, followed by a system-dependent line separator.
*
* @author Jin Kwon <onacit_at_gmail.com>
* @see System#lineSeparator()
*/
@DisplayName("main(args) prints 'hello, world' followed by a system-dependent line separator")
@Test
public void main_PrintHelloWorld_() {
final var out = System.out;
try {
// --------------------------------------------------------------------------------------------------- given
final var buffer = new ByteArrayOutputStream();
System.setOut(new PrintStream(buffer));
// ---------------------------------------------------------------------------------------------------- when
HelloWorld.main();
// ---------------------------------------------------------------------------------------------------- then
final var actual = buffer.toByteArray();
final var expected = ("hello, world" + System.lineSeparator()).getBytes(StandardCharsets.US_ASCII);
Assertions.assertArrayEquals(actual, expected);
} finally {
System.setOut(out);
}
}
有问题的部分是
.getBytes(StandardCharsets.US_ASCII)
。
我认为假设 系统相关的行分隔符使用
US_ASCII
进行编码并没有错。
%n
?
您应该使用与
buffer.toByteArray()
返回的字节数组相同的编码。
将字符串转换为字节是
PrintStream
的工作,那么你的PrintStream
使用什么编码?您通过调用 this 构造函数创建了
PrintStream
。文档说:
写入流中的字符将使用默认字符集转换为字节,或者其中 out 是 PrintStream,即打印流使用的字符集。
所以你应该使用
Charset.defaultCharset()
来解码字节数组。