如何忽略来自输入流的所有数据而不触发静态分析工具?

问题描述 投票:0回答:4

我有一个

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 来说就不会看起来像一个错误?

java inputstream findbugs
4个回答
3
投票
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 添加到您的构建依赖项中。不过,它没有添加到程序的
运行时

依赖项中。


1
投票

检查此链接

使用@SuppressWarnings排除警告

一些注意事项:

“如果没有注释,编译器会抱怨局部变量 s 从未被使用。有了注释,编译器会在 foo 方法本地默默地忽略此警告。这使得可以将警告保留在同一编译单元的其他位置或同一个项目。”


0
投票


0
投票
ProcessBuilder

来运行我想要附加其标准输出的“其他”进程。

如果我们使用 ProcessBuilder 来管理其他进程,那么从 java 9 开始我们可以重定向输出。

processBuilder.redirectOutput(ProcessBuilder.Redirect.DISCARD)

来自文档;

表示子进程的输出将被丢弃。典型的实现通过写入操作系统特定的“空文件”来丢弃输出

public static final Redirect DISCARD = new Redirect() { ... }
© www.soinside.com 2019 - 2024. All rights reserved.