2
votes

Utilisez try-with-resources ou fermez ce "BufferedReader" dans une clause "finally"

Je cherchais un moyen de résoudre ce problème. Lisez toutes les réponses précédentes mais aucune ne m'a aidé. S'agit-il d'une erreur avec SonarQube?

public class Br {

    public String loader(String FilePath){

        BufferedReader br;
        String str = null;
        StringBuilder strb = new StringBuilder();
        try {
            br = new BufferedReader(new FileReader(FilePath));
            while ((str = br.readLine()) != null) {
                strb.append(str).append("\n");
            }
        } catch (FileNotFoundException f){
            System.out.println(FilePath+" does not exist");
            return null;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return strb.toString();
    }
}


6 commentaires

Exécutez votre code 1 million de fois. Vous verrez que vous avez créé une fuite de ressources. Vous ouvrez des ressources, mais ne les fermez jamais


Il vous manque la méthode br.close () pour éviter une fuite de ressources. Ceci peut être réalisé dans un bloc finally après les blocs catch ou dans un try (BufferedReader br = new BufferedReader (new FileReader (FilePath))) {.. ..


J'ai essayé ce que vous avez dit, mais a fini par être une erreur.


Utilisez toujours par défaut try-with-resources.


Ça n'aiderait pas du tout. J'ai essayé tout ce qui a été suggéré a encore beaucoup d'autres erreurs. Si j'essaye d'ajouter finalement {}, j'obtiens "br n'a pas été initialisé". Après avoir défini br sur null, je me retrouve dans d'autres erreurs et ainsi de suite.


Je suis bizarre que vous ayez return null dans la première exception, même si votre return strb.toString () est en dehors de try , et le IOException n'a pas de valeur nulle de retour. Soit mettez return null dans les deux exceptions avec le return strb.toString () dans le try, soit laissez-le à l'extérieur sans les return null s. Cela rend simplement votre code déroutant car dans IOException, vous retournerez strb.toString (). (Ce n'est pas vraiment lié à votre autre problème cependant)


3 Réponses :


0
votes

Le code que vous avez écrit fuit en effet des ressources car vous ne fermez pas votre BufferedReader. L'extrait suivant devrait faire l'affaire:

public String loader(String filePath){
    String str = null;
    StringBuilder strb = new StringBuilder();
    // try-with-resources construct here which will automatically handle the close for you
    try (FileReader fileReader = new FileReader(filePath); 
         BufferedReader br = new BufferedReader(fileReader);){
        while ((str = br.readLine()) != null) {
            strb.append(str).append("\n");
        }
    }
    catch (FileNotFoundException f){
        System.out.println(filePath+" does not exist");
        return null;
    }
    catch (IOException e) {
        e.printStackTrace();
    }
    return strb.toString();
}

Si vous rencontrez toujours des problèmes avec ce code, alors oui, c'est la faute de SonarQubes :-)


2 commentaires

Oh ok alors c'est une erreur SonarQubes! J'ai essayé cela avant, j'ai essayé à nouveau maintenant et j'ai toujours eu la même erreur.Merci!


Peut-être un long plan, mais peut-être que SonarQube nécessite que FileReader et BufferedReader soient déclarés séparément dans la construction try-with-resources? Ajusté mon échantillon en fonction de cela.



2
votes

Il semble que vous vouliez simplement lire toutes les lignes d'un fichier. Vous pouvez utiliser ceci:

public String loader(String FilePath) {
    try(Scanner s = new Scanner(new File(FilePath).useDelimiter("\\A")) {
        return s.hasNext() ? s.next() : null;
    } catch(IOException e) {
        throw new UncheckedIOException(e);
    }
}


0 commentaires

10
votes

Vous n'appelez pas br.close () ce qui signifie risquer une fuite de ressources. Afin de fermer de manière fiable le BufferedReader , vous avez deux options:

en utilisant un bloc enfin :

public String loader(String FilePath) {
    String str = null;
    StringBuilder strb = new StringBuilder();

    // the following line means the try block takes care of closing the resource
    try (BufferedReader br = new BufferedReader(new FileReader(FilePath))) {
        while ((str = br.readLine()) != null) {
            strb.append(str).append("\n");
        }
    } catch (FileNotFoundException f) {
        System.out.println(FilePath + " does not exist");
        return null;
    } catch (IOException e) {
        e.printStackTrace();
    }

    return strb.toString();
}

en utilisant une instruction try -with-resources:

public String loader(String FilePath) {
    // initialize the reader with null
    BufferedReader br = null;
    String str = null;
    StringBuilder strb = new StringBuilder();

    try {
        // really initialize it inside the try block
        br = new BufferedReader(new FileReader(FilePath));
        while ((str = br.readLine()) != null) {
            strb.append(str).append("\n");
        }
    } catch (FileNotFoundException f) {
        System.out.println(FilePath + " does not exist");
        return null;
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        // this block will be executed in every case, success or caught exception
        if (br != null) {
            // again, a resource is involved, so try-catch another time
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    return strb.toString();
}


8 commentaires

Ok, donc la méthode avec enfin les crochets a très bien fonctionné! Je ne sais pas pourquoi essayer avec des ressources n'a pas fonctionné! Merci beaucoup!


@Lol De rien! C'est la version classique. Avez-vous essayé l'autre? SonarQube s'en est-il plaint? Pensez à accepter la réponse si cela vous a aidé, cela vous donnerait aussi un peu de réputation.


La deuxième version ne semble pas fonctionner pour moi! Donnerait la même erreur qu'avant.


@Lol C'est intéressant ... N'est-ce pas SonarQube lui-même qui a déclaré Utiliser try-with-resources ou fermer ce "BufferedReader" dans une clause "finally" ? Le titre de votre question est un message d'erreur, n'est-ce pas?


Oui c'était! Lorsque j'ai essayé d'essayer avec des ressources, je me suis retrouvé dans la même déclaration, ce qui est totalement étrange.


@Lol qui pourrait être un problème déjà connu de SonarQube ... Ce n'est pas de notre faute ;-)


Salut, j'ai ajouté try-with-resource à mon code et j'ai obtenu l'erreur «StatementIsClosedException: Aucune opération autorisée après la fermeture de l'instruction», que dois-je faire avec cela?


@Cecilia Vous ne pouvez pas accéder à la ressource en dehors de la portée du bloc try -with-resources, mais vous le faites évidemment, ce qui conduit à cette Exception . Stockez les données dont vous avez besoin dans des structures de données définies en dehors de cette portée.