Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用资源尝试使用InputStreamReader包装流的位置?_Java_Java 7 - Fatal编程技术网

Java 使用资源尝试使用InputStreamReader包装流的位置?

Java 使用资源尝试使用InputStreamReader包装流的位置?,java,java-7,Java,Java 7,我可能想得太多了,但我只是写了代码: try (InputStream in = ModelCodeGenerator.class.getClassLoader().getResourceAsStream("/model.java.txt")) { modelTemplate = new SimpleTemplate(CharStreams.toString(new InputStreamReader(in, "ascii"))); } 这意味着InputStreamReader永远不

我可能想得太多了,但我只是写了代码:

try (InputStream in = ModelCodeGenerator.class.getClassLoader().getResourceAsStream("/model.java.txt"))
{
    modelTemplate = new SimpleTemplate(CharStreams.toString(new InputStreamReader(in, "ascii")));
}
这意味着InputStreamReader永远不会关闭(但在本例中,我们知道它的close方法只是关闭底层InputStream)

可以这样写:

try (InputStreamReader reader = new InputStreamReader(...))
但这似乎更糟。如果InputStreamReader出于某种原因抛出,InputStream将永远不会关闭,对吗?C++中的常见问题是调用其他构造函数的构造函数。异常可能导致内存/资源泄漏

这里有最佳实践吗

但这似乎更糟。如果
InputStreamReader
出于某种原因抛出,则
InputStream
永远不会被关闭,对吗

这是正确的(虽然不太可能,但是
InputStreamReader
构造函数实际上做不了多少事情)

允许您声明任意数量的资源。声明一个用于包装的资源,另一个用于
InputStreamReader

try (InputStream in = ModelCodeGenerator.class
             .getClassLoader()
             .getResourceAsStream("/model.java.txt");
    InputStreamReader reader = new InputStreamReader(in)) {...}
请注意,
getResourceAsStream
可能返回
null
,这将导致
InputStreamReader
构造函数抛出
NullPointerException
。如果您想以不同的方式处理这个问题,请调整检索要打包的资源的方式

上面链接的教程展示了这个例子

try (
    java.util.zip.ZipFile zf =
         new java.util.zip.ZipFile(zipFileName);
    java.io.BufferedWriter writer = 
        java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
) {
带着解释

在本例中,try with resources语句包含两个 用分号分隔的声明:
ZipFile
BufferedWriter
。当直接跟随它的代码块 通常或由于异常而终止关闭
BufferedWriter
ZipFile
对象的方法是自动生成的 按此顺序调用。请注意,资源的close方法是 以与他们的创造相反的顺序被召唤

这意味着InputStreamReader从未关闭

嗯??在你的代码中它是。。。它当然也会处理资源流的.close()。有关更多详细信息,请参见下文

但是,您可以在try with resources语句的“资源块”中声明多个资源

这里还有一个问题:
.getResourceAsStream()
可以返回null;因此,您可能有一个NPE

如果我是你,我会这么做:

final URL url = ModelCodeGenerator.class.getClassLoader()
    .getResource("/model.java.txt");

if (url == null)
    throw new IOException("resource not found");

try (
    final InputStream in = url.openStream();
    final Reader reader = new InputStreamReader(in, someCharsetOrDecoder);
) {
    // manipulate resources
}
有一个非常重要的一点需要考虑,但是

Closeable
扩展了
AutoCloseable
,是;事实上,它只是通过抛出异常(
IOException
vs
exception
)而与“签名方式”有所不同。但在行为上有一个根本的区别

AutoCloseable
.close()
的javadoc(强调我的):

请注意,与Closeable的close方法不同,此close方法不要求是幂等的。换句话说,多次调用此close方法可能会产生一些明显的副作用,这与Closeable.close不同,Closeable.close要求在多次调用时不起作用。但是,强烈鼓励此接口的实现者使其紧密方法幂等

事实上,
Closeable
的javadoc很清楚这一点:

关闭此流并释放与之关联的所有系统资源。如果流已关闭,则调用此方法无效

你有两点非常重要:

  • 根据合同,
    可关闭的
    还负责与之相关的所有资源;因此,如果关闭一个
    缓冲读取器
    ,该读取器封装一个
    读取器
    ,该读取器封装一个
    输入流
    ,这三个读取器都将关闭
  • 如果您多次调用
    .close()
    ,则不会产生进一步的副作用

当然,这也意味着您可以选择偏执选项,保留对所有
Closeable
资源的引用并将其全部关闭;但是,如果您的组合中有
可自动关闭的
资源,而这些资源不是
可关闭的
,请小心

我想关闭这两个是安全的方法。我们知道,这有点过头了,但依赖于实现细节的安全性是一种糟糕的做法。顺便说一下,NPE很好。更新了完整的答案!谢谢你澄清你的答案!当检查NPE时,代码很明显,您只需要在try with resources中使用InputStreamReader,因为当该自动关闭时,它将关闭底层流,正如您正确指出的那样。但是,引发此问题的行为是您尝试的情况(reader=new InputStreamReader(getResourceAsStream(“…”))。在这种情况下,如果在构造InputStreamReader的过程中出现异常,那么我想象reader.close()从未被调用(reader还不存在),但流已打开,没有命名引用,并且将永远不会关闭,可能的终结器除外。在我看来,这是一个容易犯的错误,也是一个很难抓住的错误。C++更常见,是的,你说得很对。只有在try with resources块中“安全声明”的资源才会安全关闭,如果您将它们“链接”起来,则情况并非如此。