FileReader와 BufferedReader를 모두 닫아야합니까?


188

FileReader를 감싸는 BufferedReader를 사용하여 로컬 파일을 읽고 있습니다.

BufferedReader reader = new BufferedReader(new FileReader(fileName));
// read the file
// (error handling snipped)
reader.close();

수행 내가 필요 뿐만 아니라, 또는 랩퍼 핸들이? 사람들이 다음과 같은 작업을 수행하는 코드를 보았습니다.close()FileReader

FileReader fReader = new FileReader(fileName);
BufferedReader bReader = new BufferedReader(fReader);
// read the file
// (error handling snipped)
bReader.close();
fReader.close();

이 메소드는 서블릿에서 호출되며 핸들을 열어 두지 않도록하고 싶습니다.


4
이 정보에 대한 소스를 읽을 수 있습니다. JDK 설치 디렉토리의 src.zip에 있거나 온라인으로 읽을 수 있습니다 (예 : docjar.com/html/api/java/io/BufferedReader.java.html
gustafc

50
누군가에게 소스를 읽도록하는 것은 "RTFM!"을 말하는 것보다 나쁩니다. 그리고 소스에 버그가 있다면 어떨까요? 암시 적으로 우리는 올바른 행동이 무엇인지 알고 싶 습니까?
Raedwald

1
글쎄요 ...이 관점에서 볼 때 : API 사양을 가리키는 것이 더 좋지 않습니다. 소스가 문서에 지정된 것처럼 동작하지 않는 버그가 아닌 경우 문서를 신뢰할 수 없습니다. 따라서 그러한 질문에 대답하는 좋은 방법은 없습니다.
Atmocreations

@Atmocreations 다음 유지 관리 릴리스는 소스 만 보면 의존하는 버그를 유쾌하게 수정할 수 있습니다. 문서화 된 동작이 무엇인지 알아야합니다. 물론 소스를 보는 데 아무런 문제가 없지만 소스가 변경되지 않는다고 가정 할 수는 없습니다. 문서화 된 동작 변경은 일반적으로 버그 수정보다 훨씬중요 합니다.
제임스 무어

답변:


202

아니.

BufferedReader.close()

BufferedReaderInputStreamReader에 대한 javadoc에 따라 스트림을 닫습니다.

만큼 잘

FileReader.close()

그렇습니다.


12
생성자가 BufferedReader예외 를 throw 하지 않는 한 . 다른 리소스와 버퍼링을 가진 데코레이터를 조심해야하지만 기본 스트림을 닫는 것이 더 깨끗합니다.
Tom Hawtin-tackline

9
Javadoc은 BufferedReader.close()기본 리더를 닫는 지 여부를 말하지 않습니다 . 설명은에서 간단히 복사됩니다 Reader.close(). 실제로 실제 동작 일 수 있지만 문서화되어 있지 않습니다.
John Kugelman

3
실제 행동이 다르면 문서화되어 있어야합니다. 그렇지 않으면 문서가 쓸모가 없습니다. 프로그래머는 문서를 완전하고 구체적으로 간주 할 수 있어야합니다.
Atmocreations

6
실제 문서가 변경되었는지 또는 변경되어서는 안되는지는 중요하지 않습니다. Reader#close()javadoc은 랩핑 된 Reader를 닫는 지 여부를 말하지 않습니다. 그것과 관련된 모든 것은 Closes the stream and releases any system resources associated with it.자원을 닫거나 닫지 않는다고 말할 정도로 명확하지 않습니다. '자원 공개'는 BufferedReader의 자원에 대한 참조를 제거하는 것일 수도 있습니다. 이는 자원이 닫히지 않았 음을 의미합니다.
searchengine27

99

다른 사람들이 지적했듯이 외부 래퍼 만 닫으면됩니다.

BufferedReader reader = new BufferedReader(new FileReader(fileName));

BufferedReader생성자가 예외를 던지면 파일 핸들이 누출 될 가능성이 매우 적습니다 (예 :) OutOfMemoryError. 앱이이 상태 인 경우 다른 프로그램에 할당하려는 리소스의 OS를 박탈하지 않는 것이 얼마나 중요한지에 따라 정리가 얼마나주의를 기울여야하는지가 중요합니다.

닫기 가능한 래퍼 생성자는 자바 5 또는 6에 실패 할 경우 인터페이스를 사용할 수 있습니다 :

Reader reader = new FileReader(fileName);
Closeable resource = reader;
try {
  BufferedReader buffered = new BufferedReader(reader);
  resource = buffered;
  // TODO: input
} finally {
  resource.close();
}

Java 7 코드는 try-with-resources 패턴을 사용해야합니다 .

try (Reader reader = new FileReader(fileName);
    BufferedReader buffered = new BufferedReader(reader)) {
  // TODO: input
}

1
"자바 7 코드는 try-with-resources 패턴을 사용해야합니다." 고마워, 바로 내가 찾던 것입니다. 이 솔루션은 '09 년에 작성되었으므로 try-with-resources 패러다임은 아마도 새로운 권장 사항이되어야합니다. 또한, 승인되고 높은 투표 응답보다 OP에 대한 더 나은 답변을 제공합니다.
tresf

5

BufferedReader 소스에 따르면이 경우 bReader.close는 fReader.close를 호출하므로 기술적으로 후자를 호출 할 필요가 없습니다.


사용 방법을 설명하는 설명서가 있으므로 먼저 설명서를 봐야합니다. 코드의 편차는 버그입니다.
hmijail의 신음은 resignees


4

소스 코드를 확인한 후 예제에서 다음을 발견했습니다.

FileReader fReader = new FileReader(fileName);
BufferedReader bReader = new BufferedReader(fReader);

의 close () 메소드 의 BufferedReader 객체의 추상 근접 () 메서드를 호출 할 리더 궁극적에서 구현 된 메서드를 호출 할 클래스 InputStreamReader의 다음 닫 클래스 의 InputStream 객체를.

따라서 bReader.close ()만으로 충분합니다.


4
소스 코드가 보여주는 것은 참조로 인용 할 수 없습니다. 그것은 무엇 사양 에 의존 할 수있다이 경우 Javadoc의에서 말했다.
Lorne의 후작

1

Java 7부터는 try-with-resources 문을 사용할 수 있습니다

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
    return br.readLine();
}

때문에 BufferedReader인스턴스가 시도 -과 - 자원 문에 선언, 그것은 상관없이 try 문이 정상적으로 갑자기 완료 여부에 종료됩니다. 따라서 finally성명서 에서 직접 닫을 필요는 없습니다 . (이것은 또한 중첩 된 자원 설명의 경우입니다)

리소스를 다룰 때 권장되는 방법 입니다. 자세한 내용은 설명서 를 참조하십시오.


이는 2009 년 @mcdowell의 답변과 거의 동일하며, 발생할 수있는 일부 사례도 다루고 있습니다.
tresf

0

bufferedReader, 즉 reader.close () 만 닫으면 정상적으로 작동합니다.


0

늦었지만

BufferReader.java :

public BufferedReader(Reader in) {
  this(in, defaultCharBufferSize);
}

(...)

public void close() throws IOException {
    synchronized (lock) {
        if (in == null)
            return;
        try {
            in.close();
        } finally {
            in = null;
            cb = null;
        }
    }
}

그 / 그녀의 질문에 대답하지 않는 Eeeeh? 그녀 는 예제 코드가 아닌 FileReader 및 BufferedReader를 닫을 필요 가 있는지 묻습니다 .
TornaxO7

@ TornaxO7 아니요, 예제 코드가 아닙니다. 방금 Java 소스 코드의 일부를 썼습니다. 따라서 ctrl / cmd 키 (IDE에 따라 다름)로 일부 BufferedReader의 기능을 클릭하면 BufferedReader의 소스 코드를 볼 수 있으며 해당 코드 조각을 찾을 수 있습니다. 따라서 BufferedReader는 FileReader 자체를 닫습니다 (이 경우 'in'은 FileReader이므로 bufferReader.close ()를 호출하면 bufferReader.close 메소드에서 정확하게 in.close ()를 호출합니다)
Dmitry 가 슈코

0

당신은 하지 마십시오 랩 리더 / 라이터를 닫아야합니다.

문서 ( Reader.close(), Writer.close())를 살펴보면 다음과 같이 표시됩니다 Reader.close().

스트림을 닫고 이와 관련된 모든 시스템 리소스를 해제합니다.

" 관련된 모든 시스템 리소스를 해제합니다"라고 말합니다 . 그것이 확인되지 않더라도 .. 그것은 당신에게 더 깊게 보이기 시작하는 너지를 준다. 그리고 당신이 Writer.close()그것에 가면 그것이 닫히고 있다는 것만 나타냅니다.

그러한 경우, 우리 는 소스 코드를 살펴보기 위해 OpenJDK 를 참조 합니다.

BufferedWriter Line 265에서을 볼 수 있습니다 out.close(). 그래서 그것은 닫히지 않습니다. 그것은 다른 것입니다. 당신이 "의 발행 수의 클래스를 검색하면 out"당신은 생성자에서 것을 알 수 있습니다 라인 87out 할당 작가에게 다음 클래스가 다른 생성자를 호출 랩이며 out그 자체에 매개 변수 out변수를 ..

그래서 .. 다른 사람들은 어떻습니까? BufferedReader Line 514 , BufferedInputStream Line 468InputStreamReader Line 199 에서 비슷한 코드를 볼 수 있습니다 . 내가 모르는 다른 사람들도 있지만 그렇게 생각하기에 충분해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.