我有一个
InputStream
附加到另一个进程的标准输出。我有时需要记录流中的数据,有时则不需要。即使我不关心输出,我仍然需要读取它,以便其他进程不会因输出缓冲区已满而阻塞。我使用以下代码有选择地记录输出:
InputStream is = ...;
boolean report = ...;
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
if (report) {
String line = null;
while ((line = br.readLine()) != null) {
Debug.println(line);
}
} else {
while (br.readLine() != null) {
}
}
但是,在第二个
while
循环中,FindBugs 会警告(RV_DONT_JUST_NULL_CHECK_READLINE)我正在调用 readLine
并仅 检查它是否为空,而不对结果执行任何操作。它的分析是正确的,但在这种情况下我不想对结果做任何事情。是否有一些惯用的方法来使用和忽略流中的所有数据,这样它对于 FindBugs 来说就不会看起来像一个错误?
String
上使用
skip
来避免构造直接被丢弃的 InputStream
对象。 (InputStreamReader
和BufferedReader
也有skip
方法,但如果你想跳过整个流,你真的不需要
InputStreamReader
的字符解码功能或行检测和BufferedReader
的缓冲区管理功能。)while (is.skip(Long.MAX_VALUE) == Long.MAX_VALUE) {
}
循环不太可能运行多次 - 您需要首先从流中读取 8 艾字节 - 但循环是为了平息另一个 FindBugs 警告 (SR_NO_CHECKED),如果您在不检查返回的情况下调用
skip
,则会发生该警告值。
使用
SuppressWarnings
注释来使编译器静音是无效的,因为不是
编译器担心未使用的返回值。该注释不会存储在编译后的代码中,因此像 FindBugs 这样的字节码分析器无论如何都看不到它。此外,
SuppressWarnings
抑制的警告均不适用于这种情况;特别是,unused
不适用,因为返回值不在编译器检查的范围内。 不过,您可以尝试使用生成警告的静态分析工具提供的其他抑制机制,而不是 Java 内置的
SuppressWarnings
。对于 FindBugs,这就是
SuppressFBWarnings
注释。import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
为了最小化警告抑制的范围,您可以将警告生成代码隔离在其自己的方法中。例如:
@SuppressFBWarnings("RV_DONT_JUST_NULL_CHECK_READLINE")
private void consumeWholeStream(BufferedReader br) throws IOException {
while (br.readLine() != null) {
}
}
然后您可以在给定的上下文中使用该方法:
if (report) {
String line = null;
while ((line = br.readLine()) != null) {
Debug.println(line);
}
} else {
consumeWholeStream(br);
}
需要注意的是,这会将 FindBugs 注释 jar 添加到您的构建依赖项中。不过,它没有添加到程序的运行时
依赖项中。
ProcessBuilder
来运行我想要附加其标准输出的“其他”进程。
如果我们使用 ProcessBuilder 来管理其他进程,那么从 java 9 开始我们可以重定向输出。processBuilder.redirectOutput(ProcessBuilder.Redirect.DISCARD)
来自文档;
表示子进程的输出将被丢弃。典型的实现通过写入操作系统特定的“空文件”来丢弃输出
public static final Redirect DISCARD = new Redirect() { ... }