Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

IO Java Discussion :

Problème avec File.mkdir()


Sujet :

IO Java

  1. #1
    Membre expérimenté
    Problème avec File.mkdir()
    Bonjour,
    Je rencontre une difficulté avec la méthode mkdir() de la classe java.io.File.
    J'utilise naturellement une instance de File avec le chemin complet vers mon nouveau dossier, puis je sollicite sa méthode mkdir() si le dossier n'existe pas.
    Le dossier est bien créé, mais il m'est impossible de le supprimer depuis l'explorateur de Windows tant que je n'ai pas quitté mon programme ?!
    Bien que dans ce dernier, l'instance de File utilisée pour créer le dossier n'est plus utilisée, mon programme ne libère pas le dossier qu'il a créé. Je ne comprends pas pourquoi ?
    Donc, encore moins comment éviter cela. En effet, j'aimerai pouvoir supprimer ce dossier même si mon programme vient de le créer et ce sans être obligé de le quitter mais je ne vois pas comment faire ?...
    Une technologie n'est récalcitrante que par ce qu'on ne la connait et/ou comprend pas, rarement par ce qu'elle est mal faite.
    Et pour cesser de subir une technologie récalcitrante, n'hésitez surtout pas à visiter les Guides/Faq du site !

    Voici une liste non exhaustive des tutoriels qui me sont le plus familiers :
    Tout sur Java, du débutant au pro : https://java.developpez.com/cours/
    Tout sur les réseaux : https://reseau.developpez.com/cours/
    Tout sur les systèmes d'exploitation : https://systeme.developpez.com/cours/
    Tout sur le matériel : https://hardware.developpez.com/cours/

  2. #2
    Membre chevronné
    salut,
    essaies cette commande depuis ton ecran de commande WINDOWS:

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    RD /S /Q chemin_de_vers_ton_repertoire


    Eric

  3. #3
    Membre expérimenté
    Salut jeffray03,
    Merci pour ton intervention. Malheureusement, même punition, la commande n'aboutit pas et affiche en ligne de commande la même erreur, à savoir que la suppression est impossible parce que ce dernier est actuellement ouvert dans une application ???
    Identique pour les fichiers contenus dans ce dossier. Le seul moyen de reprendre la main sur ces fichiers ou le dossier depuis Windows est de quitter la machine virtuelle Java ???
    Pourtant, je ne sollicite aucun flux directement, je me contente d'utiliser la méthode mkdir de la classe File pour créer un dossier de destination dans lequel ensuite je copies des fichiers via la méthode copy de la classe Files.
    Comment puis-je faire pour lâcher la main sur ces dossiers et fichiers sans être obligé de quitter la JVM ?
    Une technologie n'est récalcitrante que par ce qu'on ne la connait et/ou comprend pas, rarement par ce qu'elle est mal faite.
    Et pour cesser de subir une technologie récalcitrante, n'hésitez surtout pas à visiter les Guides/Faq du site !

    Voici une liste non exhaustive des tutoriels qui me sont le plus familiers :
    Tout sur Java, du débutant au pro : https://java.developpez.com/cours/
    Tout sur les réseaux : https://reseau.developpez.com/cours/
    Tout sur les systèmes d'exploitation : https://systeme.developpez.com/cours/
    Tout sur le matériel : https://hardware.developpez.com/cours/

  4. #4
    Expert confirmé
    Montre nous un peu de code.
    Tu ne laisses pas un flux ouvert sur un fichier de ce répertoire, par hasard ?

  5. #5
    Membre expérimenté
    C'est tout ce que je mérite....

    Ça c'était avant :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    Files.copy(fichierSource.toPath(), new FileOutputStream(fichierDestination));

    Ca c'est maintenant :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    FileOutputStream fluxSortie = new FileOutputStream(fichierDestination);
    Files.copy(fichierSource.toPath(), fluxSortie);
    fluxSortie.close();


    Et ça marche beaucoup mieux. Merci fr1man, ta remarque a fait Tilt !
    Une technologie n'est récalcitrante que par ce qu'on ne la connait et/ou comprend pas, rarement par ce qu'elle est mal faite.
    Et pour cesser de subir une technologie récalcitrante, n'hésitez surtout pas à visiter les Guides/Faq du site !

    Voici une liste non exhaustive des tutoriels qui me sont le plus familiers :
    Tout sur Java, du débutant au pro : https://java.developpez.com/cours/
    Tout sur les réseaux : https://reseau.developpez.com/cours/
    Tout sur les systèmes d'exploitation : https://systeme.developpez.com/cours/
    Tout sur le matériel : https://hardware.developpez.com/cours/

  6. #6
    Modérateur

    Pendant qu'on y est :

    Toujours gérer les flux avec un try-with-resource !

    Tu n'as aucune garantie que ton code arrivera sans encombre jusqu'au fluxSortie.close(), là. Un try-with-resource donnerait cette garantie, dont tu sais maintenant qu'elle est indispensable.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Membre expérimenté
    Merci pour cette précision, thelvin.
    Le pire, c'est que mon petit Netbeans me l'a proposé le try with ressource. Mais comme je n'avais pas encore regardé quelle différence présentait ce type de try, et que Netbeans me permet de passer outre la recommandation, j'avais conservé un try standard. Si j'avais écouté Netbeans et mis en place un try with ressource, j'aurais certainement vu passer une exception qui m'aurait fait comprendre mon erreur, je n'aurais alors embêté personne avec cette question stupide...
    En tous cas, j'ai bien retenu la leçon.
    Bonne continuation.
    Une technologie n'est récalcitrante que par ce qu'on ne la connait et/ou comprend pas, rarement par ce qu'elle est mal faite.
    Et pour cesser de subir une technologie récalcitrante, n'hésitez surtout pas à visiter les Guides/Faq du site !

    Voici une liste non exhaustive des tutoriels qui me sont le plus familiers :
    Tout sur Java, du débutant au pro : https://java.developpez.com/cours/
    Tout sur les réseaux : https://reseau.developpez.com/cours/
    Tout sur les systèmes d'exploitation : https://systeme.developpez.com/cours/
    Tout sur le matériel : https://hardware.developpez.com/cours/

  8. #8
    Expert éminent sénior
    Salut,

    Juste quelques remarques :

    • Gros +1 pour le try-with-resource, qui permet de bien libérer les ressources quoi qu'il arrive.
      C'est même primordial dans une application serveur où ce genre d'oubli peut entrainer des blocages lié à des limites systèmes.
    • J'ai remarqué que tu utilises à la fois l'ancienne API (java.io.File) et la nouvelle API (Path et Files du package java.nio.file).
      Perso je te conseillerais d'utiliser uniquement la nouvelle API si c'est possible, c'est à dire grosso-modo de remplacer File file = new File("xxx") par Path path = Paths.get("xxx") et d'utiliser les méthodes statiques de la classe Files.
      L'API est plus claire, mieux conçus et plus complète...
    • Dans ton cas précis, tu peux utiliser Files.copy(Path,Path) à la place de Files.copy(Path,OutputStream)...
      En lui passant deux "Path", non seulement tu te libères de la gestion des ressources, mais en plus cela permet à l'API d'optimiser la copie, notamment si les deux fichiers sont sur le même système de fichier...
    Cette signature n'a pas pu être affichée car elle comporte des erreurs.

  9. #9
    Membre expérimenté
    Effectivement Adigouba, c'est plus intelligent de n'utiliser que java.nio.file.Files et java.nio.file.Paths, et je ne me suis pas gêné pour corriger à nouveau le tir. Cependant, dans ce cas, pas de throw with ressource ?!
    throws with ressource n'accepte pas la classe Path.

    Résumé avec FileOutputStream :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    try (FileOutputStream fluxSortie = new FileOutputStream(fichierDestination)) {
        Files.copy(fichierSource.toPath(), fluxSortie);
        fluxSortie.close();
        }
    catch (FileNotFoundException ex) {
        ...
        }
    catch (IOException ex) {
        ...
        }


    Résumé avec java.nio.file.Path :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Path source = Paths.get("..../source.truc");
    Path destination = Paths.get("..../destination.truc");
    try {
        Files.copy(source, destination);
        }
    catch (IOException ex) {
        ...
        }


    En effet, dans le second cas, je ne peux pas utiliser try with ressource...
    Autre détail qui m'intrigue. Dans la documentation de l'API Java 8 utilisée ici, il n'y a aucune trace d'une méthode Files.copy(Path src, Path dst) ?!
    Un oubli dans le javadoc ?
    Seules trois méthode copy sont documentées , l'une prenant un InputStream en source et un Path en cible, l'autre prenant l'inverse, un Path en source et un OutputStream en cible (celle que j'utilisais au départ), et une dernière avec trois paramètres, un Path en source, un Path en cible et des options de copie. Mais je n'ai trouvé aucune méthode documentée avec un Path en source, un Path en cible et rien d'autre ???
    C'est bien dommage, car si elle avait été documentée dans l'API Java 8, je l'aurai probablement utilisée dés le début. C'est surprenant qu'elle n'apparaisse pas dans la doc ???
    Une technologie n'est récalcitrante que par ce qu'on ne la connait et/ou comprend pas, rarement par ce qu'elle est mal faite.
    Et pour cesser de subir une technologie récalcitrante, n'hésitez surtout pas à visiter les Guides/Faq du site !

    Voici une liste non exhaustive des tutoriels qui me sont le plus familiers :
    Tout sur Java, du débutant au pro : https://java.developpez.com/cours/
    Tout sur les réseaux : https://reseau.developpez.com/cours/
    Tout sur les systèmes d'exploitation : https://systeme.developpez.com/cours/
    Tout sur le matériel : https://hardware.developpez.com/cours/

  10. #10
    Expert éminent sénior
    La fermeture des ressources est à la charge de celui qui l'ouvre, donc tu n'as pas besoin d'utiliser un try-with-resource dans ce cas, tout comme tu ne l'utilisais pas pour le fichier d'entrée...

    Au passage tu n'as pas à appeler explicitement close() avec un try-with-resource. Le close() est automatique.

    Quand à la méthode copy() elle est bien documentée. C'est justement Files.copy(Path,Path,CopyOption...).
    Mais le "troisième" paramètres étant un varargs, il est variable et peut donc contenir zéro, une ou plusieurs valeurs.
    Cette signature n'a pas pu être affichée car elle comporte des erreurs.

  11. #11
    Membre expérimenté
    Merci Adiguba pour ces précisions. J'avais fini par comprendre que ce paramètre pouvant être null pouvait aussi être omis. Dans mon esprit, il était nécessaire de passer trois paramètres, quitte à mettre null en troisième paramètre. D'ailleurs, d'habitude, dans la doc. ils précisent que le paramètre peut être null. Là c'est un peu le contraire. Mais bon, c'est un détail.
    Maintenant j'ai compris deux choses supplémentaires : Bien maîtriser ses flux, et un paramètre null peut être omis.
    Bonne continuation.
    Une technologie n'est récalcitrante que par ce qu'on ne la connait et/ou comprend pas, rarement par ce qu'elle est mal faite.
    Et pour cesser de subir une technologie récalcitrante, n'hésitez surtout pas à visiter les Guides/Faq du site !

    Voici une liste non exhaustive des tutoriels qui me sont le plus familiers :
    Tout sur Java, du débutant au pro : https://java.developpez.com/cours/
    Tout sur les réseaux : https://reseau.developpez.com/cours/
    Tout sur les systèmes d'exploitation : https://systeme.developpez.com/cours/
    Tout sur le matériel : https://hardware.developpez.com/cours/

  12. #12
    Expert éminent sénior
    Citation Envoyé par yotta Voir le message
    et un paramètre null peut être omis.
    Non un paramètre null ne peut pas être omis.
    C'est surtout qu'on a affaire à un vararg.

    C'est juste que l'on a affaire a un paramètre varargs, c'est à dire défini comme cela :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    public static Path copy(Path source,
            Path target,
            CopyOption... options)


    Les 3 points derrière le nom du dernier paramètre indique que c'est un vararg, c'est à dire un paramètre qui peut prendre zéro, une ou plusieurs valeur.
    En réalité ce dernier paramètre CopyOption... est l'équivalent d'un tableau, soit CopyOption[].
    La différence c'est que l'on n'a pas à gérer le tableau manuellement, c'est le compilateur qui s'en charge :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    copy(source, target, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING);
    // équivaut à 
    copy(source, target, new CopyOption[]{StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING});
     
     
    copy(source, target, StandardCopyOption.REPLACE_EXISTING);
    // équivaut à 
    copy(source, target, new CopyOption[]{StandardCopyOption.REPLACE_EXISTING});
     
     
    copy(source, target);
    // équivaut à 
    copy(source, target, new CopyOption[0]);


    Donc du coup toutes les méthodes qui utilisent un varargs peuvent être appelé sans aucune valeur pour ce dernier paramètres.


    Les APIs "récentes" utilisent beaucoup cela lorsqu'il faut passer diverses valeurs.
    Cette signature n'a pas pu être affichée car elle comporte des erreurs.

  13. #13
    Membre expérimenté
    D'accord, le genre de truc que tu ne peux pas deviner si on ne te l'explique pas... (je suis autodidacte)
    Tu as bien fait d'insister, je serai passé complètement à côté de ce 'principe' vararg.
    Jusque là, je rangeais toujours les paramètres dans un conteneur quelconque (List, Set, Map, Vector, Object[], etc...) fourni en paramètre. Je ne savais pas que l'on pouvait faire autrement

    Donc, si je voulais calculer une moyenne sans connaître à l'avance le nombre de termes, je pourrai faire :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public double calculMoyenne(double... valeurs) {
        double reponse=0.0d;
        for (double d:valeurs) reponse+=d;
        return reponse/valeurs.length;
        }


    et ainsi calculer n'importe quelle moyenne en faisant par exemple :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    System.out.println("Moyenne de 24,53,1,9,et 14 : " + calculMoyenne(24,53,1,9,et 14));


    C'est juste génial, je découvre.
    C'est spécifique à Java ou c'est un mécanisme standard dans tous les langages ?
    Une technologie n'est récalcitrante que par ce qu'on ne la connait et/ou comprend pas, rarement par ce qu'elle est mal faite.
    Et pour cesser de subir une technologie récalcitrante, n'hésitez surtout pas à visiter les Guides/Faq du site !

    Voici une liste non exhaustive des tutoriels qui me sont le plus familiers :
    Tout sur Java, du débutant au pro : https://java.developpez.com/cours/
    Tout sur les réseaux : https://reseau.developpez.com/cours/
    Tout sur les systèmes d'exploitation : https://systeme.developpez.com/cours/
    Tout sur le matériel : https://hardware.developpez.com/cours/

  14. #14
    Modérateur

    Le problème de ton exemple, c'est qu'un vararg peut représenter un ou deux ou vingt-cinq arguments, mais aussi zéro argument.

    Et la moyenne d'aucun nombre, bon...

    Boh après tout ça peut être NaN, pourquoi pas...

    Citation Envoyé par yotta Voir le message
    C'est spécifique à Java ou c'est un mécanisme standard dans tous les langages ?
    Les varargs sont fréquents dans les langages de programmation, par exemple en C ils sont nécessaires pour fournir le fameux printf().

    Mais bon, il y a des langages qui ne les ont pas... Tels que Java avant la version Java 1.5. Avant ça, on pouvait toujours prendre un tableau en paramètre, à la place.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  15. #15
    Membre expérimenté
    Ok, j'ai bien tout compris.
    Merci à vous.
    Une technologie n'est récalcitrante que par ce qu'on ne la connait et/ou comprend pas, rarement par ce qu'elle est mal faite.
    Et pour cesser de subir une technologie récalcitrante, n'hésitez surtout pas à visiter les Guides/Faq du site !

    Voici une liste non exhaustive des tutoriels qui me sont le plus familiers :
    Tout sur Java, du débutant au pro : https://java.developpez.com/cours/
    Tout sur les réseaux : https://reseau.developpez.com/cours/
    Tout sur les systèmes d'exploitation : https://systeme.developpez.com/cours/
    Tout sur le matériel : https://hardware.developpez.com/cours/