如何在不启动静态分析工具的情况下忽略来自 InputStream 的所有数据?

How do I ignore all data from an InputStream without tripping up static-analysis tools?

我有一个 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 的错误?

尝试使用@SuppressWarnings 表示法。

勾选这个linkExcluding warnings using @SuppressWarnings

一些注意事项:

"Without the annotation, the compiler would complain that the local variable s is never used. With the annotation, the compiler silently ignores this warning locally to the foo method. This enables to keep the warnings in other locations of the same compilation unit or the same project."

InputStream is = ...;
boolean report = ...;
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
    if (report) {
        Debug.println(line);
    }
}

您可以通过在 InputStream 上使用 skip 来避免构建刚刚被丢弃的 String 对象。 (InputStreamReaderBufferedReader 也有 skip 方法,但如果你想跳过 entire 流,你并不真的需要InputStreamReader 的字符解码功能或 BufferedReader 的行检测和缓冲区管理功能。)

while (is.skip(Long.MAX_VALUE) == Long.MAX_VALUE) {
}

循环不太可能 运行 不止一次——你需要先从流中读取 8 艾字节——但循环是为了平息另一个 FindBugs 警告 (SR_NO_CHECKED)如果您调用 skip 而不检查 return 值,就会发生这种情况。


使用 SuppressWarnings 注释使编译器静音是无效的,因为它不是 编译器 担心未使用的 return 值。注释未存储在编译后的代码中,因此像 FindBugs 这样的字节码分析器无论如何也看不到它。此外,SuppressWarnings 抑制的警告中的 none 适用于这种情况;特别是,unused 不适用,因为 return 值 不在编译器检查的范围内。

不过,您可以尝试使用生成警告的静态分析工具提供的一些其他抑制机制,而不是 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 添加到您的构建依赖项中。不过,它没有添加到程序的 运行-time 依赖项中。