중첩된 각 Output Stream과 Writer를 개별적으로 닫아야 합니까?
코드를 쓰고 있습니다.
OutputStream outputStream = new FileOutputStream(createdFile);
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(gzipOutputStream));
다음과 같이 모든 스트림 또는 라이터를 닫아야 합니까?
gzipOutputStream.close();
bw.close();
outputStream.close();
아니면 마지막 스트림을 닫아도 될까요?
bw.close();
하고, 네,만 하면 .bw
이러한 스트림 구현에는 문제가 없지만, 이는 큰 가정입니다.
예외를 발생시키는 후속 스트림을 구성하는 문제가 이전 스트림을 중단하지 않도록 리소스 사용(튜토리얼)을 사용합니다.따라서 기본 스트림을 종료하기 위한 호출을 스트림 구현에 의존할 필요가 없습니다.
try (
OutputStream outputStream = new FileOutputStream(createdFile);
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);
OutputStreamWriter osw = new OutputStreamWriter(gzipOutputStream);
BufferedWriter bw = new BufferedWriter(osw)
) {
// ...
}
「 」는, 「 」에 콜 된 것에 해 주세요.close
★★★★★★★★★★★★★★★★★★.
중요사항:리소스 시도에서 닫히려면 변수를 열 때 스트림을 변수에 할당해야 합니다. 네스팅을 사용할 수 없습니다.nesting을 사용하는 경우 이후의 스트림 중 하나를 구성할 때 예외가 발생합니다(예:GZIPOutputStream
)는, 네스트 된 콜에 의해서 작성된 스트림을 열어 둡니다.JLS © 14.20.3부터:
리소스 사용 문은 변수(리소스라고 함)를 사용하여 매개 변수화되며, 변수(리소스라고 함)는 다음 명령어를 실행하기 전에 초기화됩니다.
try
후 역순으로 .기된된 、 행행후후후try
"변수"라는 단어에 주목하십시오(내 강조점).
예: 이 작업을 수행하지 마십시오.
// DON'T DO THIS
try (BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(
new GZIPOutputStream(
new FileOutputStream(createdFile))))) {
// ...
}
...컨스트럭터로부터의 예외(이 예외는 던질 수 있습니다)IOException
FileOutputStream
오픈. 어떤 리소스는 던질 수 있는 컨스트럭터를 가지고 있고 어떤 리소스는 가지고 있지 않기 때문에 그것들을 따로 나열하는 것은 좋은 습관입니다.
이 프로그램으로 JLS 섹션의 해석을 재확인할 수 있습니다.
public class Example {
private static class InnerMost implements AutoCloseable {
public InnerMost() throws Exception {
System.out.println("Constructing " + this.getClass().getName());
}
@Override
public void close() throws Exception {
System.out.println(this.getClass().getName() + " closed");
}
}
private static class Middle implements AutoCloseable {
private AutoCloseable c;
public Middle(AutoCloseable c) {
System.out.println("Constructing " + this.getClass().getName());
this.c = c;
}
@Override
public void close() throws Exception {
System.out.println(this.getClass().getName() + " closed");
c.close();
}
}
private static class OuterMost implements AutoCloseable {
private AutoCloseable c;
public OuterMost(AutoCloseable c) throws Exception {
System.out.println("Constructing " + this.getClass().getName());
throw new Exception(this.getClass().getName() + " failed");
}
@Override
public void close() throws Exception {
System.out.println(this.getClass().getName() + " closed");
c.close();
}
}
public static final void main(String[] args) {
// DON'T DO THIS
try (OuterMost om = new OuterMost(
new Middle(
new InnerMost()
)
)
) {
System.out.println("In try block");
}
catch (Exception e) {
System.out.println("In catch block");
}
finally {
System.out.println("In finally block");
}
System.out.println("At end of main");
}
}
...이 출력은 다음과 같습니다.
예시$의 작성내부 모스트예제 $중간 구성구성 예$OuterMost캐치블록 내최종 블록 내메인 종료 시
「」에의 콜은 것에 해 주세요.close
contract.discontracts.
★★★를 main
:
public static final void main(String[] args) {
try (
InnerMost im = new InnerMost();
Middle m = new Middle(im);
OuterMost om = new OuterMost(m)
) {
System.out.println("In try block");
}
catch (Exception e) {
System.out.println("In catch block");
}
finally {
System.out.println("In finally block");
}
System.out.println("At end of main");
}
적절한 수 있습니다.close
삭제:
예시$의 작성내부 모스트예제 $중간 구성구성 예$OuterMost예$중간폐쇄예 $InnerMost가 닫힘예 $InnerMost가 닫힘캐치블록 내최종 블록 내메인 종료 시
두 번 콜을 (으, 2번 합니다.InnerMost#close
,Middle
는 리소스 사용 Recommendications 사용 시도)입니다
대부분의 외부 스트림을 닫을 수 있습니다. 실제로 랩된 모든 스트림을 유지할 필요는 없으며 Java 7 리소스 시도 기능을 사용할 수 있습니다.
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
new GZIPOutputStream(new FileOutputStream(createdFile)))) {
// write to the buffered writer
}
YAGNI(You-int-gonna-need-it)에 가입하는 경우 실제로 필요한 코드만 추가해야 합니다.필요한 코드를 추가해서는 안 되지만 실제로는 도움이 되지 않습니다.
이 예를 들어, 이렇게 하지 않으면 어떤 문제가 발생할 수 있고 어떤 영향이 있을지 상상해 보십시오.
try (
OutputStream outputStream = new FileOutputStream(createdFile);
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);
OutputStreamWriter osw = new OutputStreamWriter(gzipOutputStream);
BufferedWriter bw = new BufferedWriter(osw)
) {
// ...
}
FileOutputStream을 하겠습니다.open
든든 、 을을일일일도 。
/**
* Opens a file, with the specified name, for overwriting or appending.
* @param name name of file to be opened
* @param append whether the file is to be opened in append mode
*/
private native void open(String name, boolean append)
throws FileNotFoundException;
파일을 찾을 수 없는 경우 닫을 기본 리소스가 없으므로 파일을 닫아도 아무런 차이가 없습니다.파일이 존재하는 경우 FileNotFoundException을 던져야 합니다.따라서 이 라인에서만 리소스를 닫으려고 해도 아무런 이점이 없습니다.
파일을 닫아야 하는 이유는 파일을 정상적으로 열었지만 나중에 오류가 발생할 경우입니다.
다음 을 볼까요?GZIPOutputStream
예외를 발생시킬 수 있는 코드가 있습니다.
private void writeHeader() throws IOException {
out.write(new byte[] {
(byte) GZIP_MAGIC, // Magic number (short)
(byte)(GZIP_MAGIC >> 8), // Magic number (short)
Deflater.DEFLATED, // Compression method (CM)
0, // Flags (FLG)
0, // Modification time MTIME (int)
0, // Modification time MTIME (int)
0, // Modification time MTIME (int)
0, // Modification time MTIME (int)
0, // Extra flags (XFLG)
0 // Operating system (OS)
});
}
그러면 파일의 헤더가 기록됩니다.쓰기 위해 파일을 열 수 있지만 8바이트도 쓸 수 없는 것은 매우 드문 일이지만, 이런 일이 발생할 수 있고 그 후에는 닫지 않습니다.파일이 닫히지 않으면 어떻게 됩니까?
플러시되지 않은 쓰기는 수신되지 않고 폐기됩니다.이 경우 스트림에 정상적으로 입력된 바이트는 이 시점에서 버퍼링되지 않습니다.그러나 닫히지 않은 파일은 영원히 존속하지 않습니다.대신 FileOutputStream은
protected void finalize() throws IOException {
if (fd != null) {
if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
flush();
} else {
/* if fd is shared, the references in FileDescriptor
* will ensure that finalizer is only called when
* safe to do so. All references using the fd have
* become unreachable. We can call close()
*/
close();
}
}
}
파일을 전혀 닫지 않으면 즉시 닫히지 않습니다(또한 말씀드렸듯이 버퍼에 남아 있는 데이터는 이렇게 손실되지만 이 시점에는 없습니다).
파일을 즉시 닫지 않으면 어떤 결과가 초래됩니까?정상적인 상황에서는 일부 데이터가 손실될 수 있으며 파일 설명자가 부족할 수 있습니다.그러나 파일을 작성할 수 있지만 쓸 수 없는 시스템이 있다면 더 큰 문제가 발생합니다.즉, 실패하더라도 이 파일을 반복적으로 작성하려고 하는 이유를 상상하기 어렵습니다.
OutputStreamWriter와 BufferedWriter는 모두 IOException을 컨스트럭터에 넣지 않기 때문에 어떤 문제가 발생하는지 명확하지 않습니다.BufferedWriter의 경우 Out Of Memory Error가 발생할 수 있습니다.이 경우 GC가 즉시 트리거되며 앞에서 설명한 바와 같이 파일이 닫힙니다.
모든 스트림이 인스턴스화된 경우 가장 바깥쪽만 닫으면 됩니다.
인터페이스의 메뉴얼에는, 다음의 방법으로 종료한다고 기재되어 있습니다.
이 스트림을 닫고 관련된 시스템리소스를 해방합니다.
릴리스 시스템 리소스에는 닫힘 스트림이 포함됩니다.
또, 다음과 같이 기술되어 있습니다.
스트림이 이미 닫혀 있는 경우 이 메서드를 호출해도 효과가 없습니다.
따라서 나중에 명시적으로 닫으면 문제가 발생하지 않습니다.
차라리 사용하는게 낫겠다.try(...)
구문(Java 7). 예를 들어,
try (OutputStream outputStream = new FileOutputStream(createdFile)) {
...
}
마지막 스트림만 닫으면 됩니다. 종료 콜은 기본 스트림에도 전송됩니다.
아니요, 최상위 수준입니다.Stream
또는reader
모든 기본 스트림/리더가 닫힙니다.
체크하다close()
최상위 스트림의 메서드 구현.
Java 7 에서는, 자원에 의한 기능 시행이 있습니다.스트림을 명시적으로 닫을 필요는 없습니다.그것은 처리됩니다.
언급URL : https://stackoverflow.com/questions/28276423/is-it-necessary-to-close-each-nested-outputstream-and-writer-separately
'programing' 카테고리의 다른 글
동기 클러스터링과 비동기 클러스터링 (0) | 2022.12.27 |
---|---|
Python의 정적 메서드? (0) | 2022.12.27 |
서버에서 mod_rewrite가 활성화 되어 있는지 확인하는 방법 (0) | 2022.11.27 |
MySQL general_log 파일 크기를 제한하는 방법 (0) | 2022.11.27 |
Laravel OrderBy 관계 수 (0) | 2022.11.27 |