Java renameTo

Bonjour, le code suivant renomme bien le fichier mais pourquoi getName garde-t-il l’ancien nom ?

[code] File fichier = new File("/home/eric/Bureau/0002008.csv");

	String nom = fichier.getCanonicalPath().replaceAll("csv", "txt");
	System.out.println(nom);
	System.out.println("avant "+fichier.getCanonicalPath());
	System.out.println(fichier.renameTo(new File(nom)));
	System.out.println("après "+fichier.getName());[/code]

donne :

/home/eric/Bureau/0002008.txt avant /home/eric/Bureau/0002008.csv true après 0002008.csv

je dois faire un fichier = new File("/home/eric/Bureau/0002008.txt");

Normal ?

Je comportement ne me surprend pas plus que ça.

[quote=“blaisoth”]je dois faire un fichier = new File("/home/eric/Bureau/0002008.txt");

Normal ?[/quote]
Ou plus simple :

Merci !

Quand tu ouvres un fichier, le système te renvoie ce qu’on appelle un descripteur de fichier (une valeur arbitraire que le kernel sait associer au contenu du fichier ; sous Windows on appelle ça un handle). Même si tu ne le vois pas directement à cause de ta classe qui te cache cette information, c’est ce descripteur qui est la seule manière d’accéder au contenu du fichier ouvert.
Quand tu renommes un fichier pendant qu’il est déjà ouvert, seul son nom change, les descripteurs existants restent valables pour accéder au contenu du fichier.
Quand tu supprimes un fichier pendant qu’il est déjà ouvert, il ne fait que disparaître de l’arborescence mais son contenu continue d’exister tant que tu as des descripteurs qui pointent vers ce fichier.

Maintenant que ça c’est clair (tu le savais probablement déjà, mais ça fait pas de mal de le rappeler), ta question est en réalité : pourquoi getName ne retrouve-t-il pas le nom du fichier à partir de son descripteur ?
Dans ta classe, le nom de fichier est en fait mémorisé au moment de la création de l’objet et ne peut plus changer ensuite vu qu’il est impossible de retrouver de manière fiable un nom de fichier à partir de son descripteur : le fichier peut très bien ne plus avoir aucun nom (supprimé entre temps) ou, plus drôle, avoir plusieurs noms (hardlinks).

Bref, ce comportement est tout à fait normal. :wink:

L’analogie avec les descripteur de fichier ne me semble pas si pertinente. En effet on écris pas dans un File en java. Le descripteur de fichier n’est créé que lorsque l’on crée un File{Out,In}putStream par exemple. Quand tu regarde les appels système simples (prévue pour l’utilisateur) pour faire des actions sur les inodes (renommage etc), elles prennent en paramètre des char*.

Je pense qu’à aborder ce sujet, ce qu’il faut c’est comprendre qu’un objet de la classe File n’est pas « connecté » au système de fichier. Tu peut très bien faire un new File(“coucou je met des caractères interdits dans mes chemins de fichiers”) sans avoir d’erreur.

Comme je viens de le dire il n’y a pas de descripteur dans la boucle, mais d’un point de vue purement technique il pourrait très bien faire :

public boolean renameTo(File dest) { // code if (success) { this.name = dest.getName(); } return success; }

C’est sans doute possible (du moins sous linux), je crois que lsof est capable de le faire (il permet par exemple de trouver des fichiers supprimé mais encore ouvert).

Je pense que c’est surtout une question de choix de la par des concepteurs de Java.

[quote=“MisterFreez”]L’analogie avec les descripteur de fichier ne me semble pas si pertinente. En effet on écris pas dans un File en java. Le descripteur de fichier n’est créé que lorsque l’on crée un File{Out,In}putStream par exemple.
[…]
un objet de la classe File n’est pas « connecté » au système de fichier. Tu peut très bien faire un new File(“coucou je met des caractères interdits dans mes chemins de fichiers”) sans avoir d’erreur.[/quote]
Ah ça je ne le savais pas, je pensais que la classe File fonctionnait comme (presque) partout ailleurs (ouverture immédiate). Tu admettras que c’était une hypothèse assez peu risquée même si sur ce coup là j’ai pas eu de chance et que je me suis planté. :wink:

En fait lsof se base sur /proc/PID/fd/ (liens symboliques pointant vers les fichiers d’origine) pour retrouver ses petits. Même si un fichier est supprimé, son lien symbolique dans /proc persiste ce qui permet de retrouver son ancien nom.

Mais au delà de lsof ou de Java, c’est l’organisation même des filesystems qui rend cette action “retrouver LE nom d’un fichier à partir de son descripteur” impossible : un fichier est en réalité un inode (non nommé) auquel peuvent correspondre zéro ou plus entrées de répertoire. À partir du moment où cette relation 1-n existe je ne vois pas comment on peut retrouver LE nom d’un fichier, au mieux on peut retrouver LES noms de fichier associés à un inode donné (et encore, même pas de manière directe : il faut parcourir l’ensemble du filesystem et comparer l’inode de chaque fichier avec l’inode recherché, il n’y a pas de liaison inode -> noms).
C’est dans ce sens là que je disais que ça ne peut pas être fiable.

[quote=“syam”][quote=“MisterFreez”]L’analogie avec les descripteur de fichier ne me semble pas si pertinente. En effet on écris pas dans un File en java. Le descripteur de fichier n’est créé que lorsque l’on crée un File{Out,In}putStream par exemple.
[…]
un objet de la classe File n’est pas « connecté » au système de fichier. Tu peut très bien faire un new File(“coucou je met des caractères interdits dans mes chemins de fichiers”) sans avoir d’erreur.[/quote]
Ah ça je ne le savais pas, je pensais que la classe File fonctionnait comme (presque) partout ailleurs (ouverture immédiate). Tu admettras que c’était une hypothèse assez peu risquée même si sur ce coup là j’ai pas eu de chance et que je me suis planté. :wink: [/quote]
C’est je pense, ce qui a induit en erreur blaisoth.

Pour le reste je comprends, je voulais surtout dire qu’au niveau d’un applicatif Java ça viens plus d’un choix des concepteurs que d’une contrainte. Le problème viendrait plus pour récupérer le nom de fichier à partir d’un FileOutputStream (qui d’ailleurs possède une méthode getFD() :wink: )