web-dev-qa-db-ja.com

java最後にブロックしてストリームを閉じるようにしてください

Finallyブロックでストリームを閉じたいのですが、IOExceptionがスローされるため、閉じるためにtryブロックに別のfinallyブロックをネストする必要があるようですストリーム。それは正しい方法ですか?少しぎこちないようです。

これがコードです:

 public void read() {
    try {
        r = new BufferedReader(new InputStreamReader(address.openStream()));
        String inLine;
        while ((inLine = r.readLine()) != null) {
            System.out.println(inLine);
        }
    } catch (IOException readException) {
        readException.printStackTrace();
    } finally {
        try {
            if (r!=null) r.close();
        } catch (Exception e){
            e.printStackTrace();
        }
    }


}
32
jhlu87

少しぎこちないようです。

そうです。少なくともJava7のリソースでの試行はそれを修正します。

Java7以前では、それを飲み込むcloseStream関数を作成できます。

public void closeStream(Closeable s){
    try{
        if(s!=null)s.close();
    }catch(IOException e){
        //Log or rethrow as unchecked (like RuntimException) ;)
    }
}

または、try ...を最後にtryキャッチ内に配置します。

try{
    BufferedReader r = new BufferedReader(new InputStreamReader(address.openStream()));
    try{

        String inLine;
        while ((inLine = r.readLine()) != null) {
            System.out.println(inLine);
        }
    }finally{
        r.close();
    }
}catch(IOException e){
    e.printStackTrace();
}

それはより冗長で、finallyの例外はtryで1つを隠しますが、意味的にはJava 7.で導入された try-with-resources に近いです。

24
ratchet freak

また、Java 7を使用している場合は、 try-with-resourcesステートメント を使用できます。

try(BufferedReader r = new BufferedReader(new InputStreamReader(address.openStream()))) {
    String inLine;
    while ((inLine = r.readLine()) != null) {
        System.out.println(inLine);
    }
} catch(IOException readException) {
    readException.printStackTrace();
}           
35
Steven Goldade

Java 7ではこれを行うことができます...

_try (BufferedReader r = new BufferedReader(...)){
     String inLine;
     while ((inLine = r.readLine()) != null) {
          System.out.println(inLine);
     }
} catch(IOException e) {
   //handle exception
}
_
  • Tryブロックで変数を宣言するには、 AutoCloseable を実装する必要があります。
  • また、tryブロックで変数を宣言すると、そのスコープがtryブロックに制限されます。
  • Tryブロックで宣言された変数は、tryブロックが終了すると自動的にclose()が呼び出されます。

これは Try with resourcesステートメント と呼ばれます。

23
Jeffrey

はい、それは不格好で醜くて混乱しています。 1つの可能な解決策は、 closeQuietly メソッドを提供する Commons IO を使用することです。

このページの右側の「関連」列には実際に重複している質問がいくつかあります。この問題を処理する他のいくつかの方法について、これらを確認することをお勧めします。

8
fvu

Commons IOライブラリについて言及している回答のように、 Google Guava Libraries には、Java.io.Closeableなどの類似のヘルパーメソッドがあります。クラスは com.google.common.io.Closeables 。探している関数の名前は、Commons IO:closeQuietly()と同様です。

または、次のように自分でロールして束を閉じることもできます:Closeables.close(closeable1、closeable2、closeable3、...):

import Java.io.Closeable;
import Java.util.HashMap;
import Java.util.Map;

public class Closeables {
  public Map<Closeable, Exception> close(Closeable... closeables) {

  HashMap<Closeable, Exception> exceptions = null;

  for (Closeable closeable : closeables) {
    try {
      if(closeable != null) closeable.close();
    } catch (Exception e) {
        if (exceptions == null) {
          exceptions = new HashMap<Closeable, Exception>();
        }
        exceptions.put(closeable, e);
      }
    }

    return exceptions;
  }
}

そして、それはスローされた例外のマップを返すか、何もない場合はnullを返します。

5
Jord Sonneveld

最終的に内のあなたのアプローチは正しいです。 finallyブロックで呼び出すコードが例外をスローする可能性がある場合は、必ず処理するか、ログに記録してください。最終ブロックから気泡が出ないようにしてください。

Catchブロック内で、例外を飲み込んでいます-これは正しくありません。

ありがとう...

2

コードで最初に気付いたのは、中括弧{}をコードから見た場合、それが抜けていることです。また、rの値をnullに初期化する必要があるため、最初にnull値をオブジェクトに渡して、作成した条件がnot null条件チェックを行い、ストリームを閉じます。

0
surendrapanday
public void enumerateBar() throws SQLException {
    Statement statement = null;
    ResultSet resultSet = null;
    Connection connection = getConnection();
    try {
        statement = connection.createStatement();
        resultSet = statement.executeQuery("SELECT * FROM Bar");
        // Use resultSet
    }
    finally {
        try {
            if (resultSet != null)
                resultSet.close();
        }
        finally {
            try {
                if (statement != null)
                    statement.close();
            }
            finally {
                connection.close();
            }
        }
    }
}

private Connection getConnection() {
    return null;
}

ソース 。このサンプルは私にとって役に立ちました。

0
dea.diana