关闭来自方法的 return 资源

Closing resource coming as return from method

我有一个助手 class,它有一个静态方法 returns 一个流:

public static InputStream getDocument(File file) throws IOException {
    ZipFile zipFile = new ZipFile(file);
    return zipFile.getInputStream(zipFile.getEntry("entry"));
}

另一个 class 访问该方法并使用返回的流:

InputStream is = MyClass.getDocument(new File(str));

我的代码有效。


但是,according to the Java Documentation,我应该关闭我的资源:

A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement.

但是,当我实施 try-with-resources:

public static InputStream getDocument(File file) throws IOException {
    try (ZipFile zipFile = new ZipFile(file);) {
        return zipFile.getInputStream(zipFile.getEntry("entry"));
    }
}

try-finally:

public static InputStream getDocument(File file) throws IOException {
    InputStream is = null;
    try {
        ZipFile zipFile = new ZipFile(docx);
        is = zipFile.getInputStream(zipFile.getEntry("entry"));
        return is;
    } finally {
        is.close();
    }
}

我遇到异常:

java.io.IOException: Stream closed

如何确保该资源将在使用后关闭?

通常调用者负责close/release资源。
您可以在方法外部使用 try-with-resourcetry-finally 构造,如下所示:

try (InputStream is = getDocument(aFile) {
    //… do your stuff
}

如果我可以给你建议,写在方法文档中:

/**
  * The caller is required to close the returned {@link InputStream}
  */
public static InputStream getDocument(File file) throws IOException

try-with-resources 与您使用 finally 的第二种方法隐含地相同。无法关闭 zipFile,但 return 基于此 zipFile 的 inputStream。

通常最好避免使用此辅助方法并使用具有多个资源的单个 try-with-resourrces:

try (
   ZipFile zipFile = new ZipFile(file);
   inputStream inputStream = zipFile.getInputStream(zipFile.getEntry("entry"));
) {
    // Do stuff
} // Both zipFile and inputStream closed here implicitly

如果您需要创建这样的方法,您可以确保当流关闭时,zipFile 对象也会关闭。

来自相关问题Does a ZipEntry persist after a ZipFile is closed?

zipFile = new ZipFile(file);
InputStream zipInputStream = ...
return new InputStream() {
    @Override
    public int read() throws IOException {
        return zipInputStream.read();
    }
    @Override
    public void close() throws IOException {
        // Better add try/catch around each close()
        zipInputStream.close();
        zipFile.close();
    }
}

这样,当调用方法关闭它接收的流时,zip 文件也会关闭。