File.exists () renvoie false quand le fichier existe

90

J'ai rencontré un bug sur lequel je n'arrive pas à trouver de logique. J'ai cet objet File, qui est créé comme ceci:

File file = new File("utilities/data/someTextFile.txt");

Je fais alors file.exists(), et ça revient false(!?). Si le fichier n'est pas trouvé, je me connecte f.getAbsolutePath()à un fichier. Quand je regarde le chemin, cela semble correct. Je peux copier-coller le chemin complet dans la fenêtre «Exécuter» de Windows et le fichier s'ouvre correctement.

Le fichier existe à tout moment et n'est ni supprimé ni modifié lors de l'exécution de mon application. Il est situé à la machine locale.

Cela ne semble se produire que dans certaines situations. Je peux reproduire le défaut à tout moment, mais je suis sûr que le chemin de l'objet fichier n'est pas modifié par les actions que je fais pour reproduire le défaut.

Qu'est-ce qui peut provoquer un file.exists()retour faux? Cela a-t-il quelque chose à voir avec les autorisations ou les verrous de fichiers, etc.?

atsjoo
la source
Alors, est-il possible de lire à partir du fichier même si exist () renvoie false?
Harry Lime
oui, je peux lire le fichier même si exist () renvoie false.
atsjoo
1
Que faut-il exactement pour reproduire le défaut?
user85421
1
C'est à l'intérieur d'une application qui appelle des fonctions écrites en matlab et compilées dans l'application java. Il semble que les fonctions matlab qui modifient le "répertoire courant" provoquent l'apparition du problème. J'utilise le chemin absolu lors de la création de l'objet fichier, donc cela ne devrait pas être un problème - peu importe ce qu'il semble être. J'ai bien sûr vérifié le chemin absolu de l'objet fichier, et il est correct (le même qu'avant que la fonction matlab change le répertoire courant).
atsjoo
7
Travaillez-vous par hasard sur un répertoire distant (par exemple un montage NFS)?
Tomer Gabel

Réponses:

42

Je vois la situation suivante sous Windows 7:

file.exists() == false
file.getAbsoluteFile().exists() == true

Le fichier en question est "var \ log", le chemin absolu fait référence à un fichier existant qui se trouve dans un sous-répertoire normal (pas un magasin virtuel). Ceci est vu de l'IDE.

Roman Zenka
la source
16
Je viens de le comprendre: bugs.sun.com/bugdatabase/view_bug.do;:YfiG?bug_id=4483097 Apparemment, les opérations exécutées sur le fichier sont résolues par rapport au répertoire actuel, tandis que getAbsolutePath se résout par rapport à user.dir. Si ces deux chemins ne correspondent pas, vous obtenez des résultats contradictoires. Diabolique!
Roman Zenka
3
J'ai exactement le même problème que j'ai essayé d'utiliser les deux méthodes pour vérifier si le fichier existe, et j'obtiens toujours faux sur Windows 7 uniquement! Une idée?
Dejell le
@Odelya: Quel IDE utilisez-vous? À quoi votre -Duser.dir est-il défini? Mon problème a été causé par la configuration de -Duser.dir dans un répertoire différent de celui de travail actuel.
Roman Zenka
1
Pour toute personne travaillant sur un projet Web dynamique, l'utilisation de file.exists () lèvera une exception, utilisez file.getAbsoluteFile (). Exists () pour rechercher des fichiers dans le répertoire WEB-INF (astuce générale, pas spécifique à Windows 7 ).
PS
Envisagez de créer un contrôle qualité distinct pour cette réponse et ces commentaires
Bato-Bair Tsyrenov
17

Il semble qu'il y ait une différence sur la façon dont le chemin est spécifié en Java.

Par exemple, si le chemin du fichier est spécifié comme file:/C:/DEV/test.txtalors

File f = new File(filename);
f.exists();

reviendra false. Le chemin peut fonctionner dans l'explorateur ou dans le navigateur, mais il s'agit d'une URL et non d'un chemin de fichier absolu.

Mais d'un autre côté, si le chemin du fichier est spécifié comme C:/DEV/test.txtalors

File f = new File(filename);
f.exists();

retournera truecar le chemin n'est pas une URL, mais c'est un chemin absolu.

Avec Spring Framework, c'est exactement ce que ResourceUtils.getFile(filename)fait - où le nom peut être une URL ou le chemin de fichier absolu.

Garima Bathla
la source
5
Je ne m'attendrais pas file:/C:/DEV/test.txtà travailler comme chemin d'accès. C'est une URL et non un chemin. Alors que certaines personnes font cette erreur, il n'y a aucune preuve que l'OP a ...
Stephen C
15

Si le processus ne dispose pas des autorisations nécessaires pour dire si un fichier existe, il retournera false. Il peut être possible d'ouvrir un fichier, mais ne pas dire par les méthodes normales s'il existe.

Tom Hawtin - Tacle
la source
20
Intéressant. Pouvez-vous développer davantage sur ce sujet? Quelles autorisations spécifiques avez-vous en tête?
Clément
Ici, java.nio.file.AccessDeniedException peut bloquer la capacité de bloquer l'existence d'un fichier / répertoire. Par exemple, si vous gardez le répertoire ouvert dans FAR ou un autre explorateur de fichiers, puis supprimez le répertoire avec tous les fichiers imbriqués et vérifiez l'existence de ce répertoire, vous pouvez alors obtenir AccessDeniedException (étend IOException) pour le fichier temporaire conservé pour vous. Dans ce cas, Files.exists renvoie false pour IOException.
beluha
11

Les réponses ci-dessus n'ont pas aidé dans mon cas. Comme indiqué ci-dessus, j'avais:

file.exists() => false
file.getAbsoluteFile().exists => true

La cause principale de cela était que le propriétaire de la machine Windows 7 avait modifié le registre pour CMD afin qu'il exécute automatiquement une commande à lancer dans un répertoire spécifique pour fonctionner avec Python. Cette modification a paralysé le code Java 1.6 qui utilise apparemment CMD sous Windows pour certaines opérations sur les fichiers, telles que exists(). L'élimination de l'exécution automatique du registre a résolu le problème.

Karl Lew
la source
1
3,5 ans plus tard, et j'ai rencontré le même problème. J'ai fait configurer un script autorun pour configurer les variables d'environnement chaque fois que je lance cmd.com. Il n'a même pas changé le répertoire actuel - juste quelques macros doskey et quelques variables d'environnement. J'ai supprimé l'autorun, et j'ai simplement exécuté manuellement les commandes dans le fichier, et soudainement File.exists () fonctionne correctement.
Homr Zodyssey
1
OMG, cela fonctionne vraiment (les deux), je cherchais bêtement le mauvais fichier et suis tombé sur cette question pour savoir pourquoi aucun d'entre eux ne fonctionne pour moi :) BTW, il semble qu'il ()manque dans la deuxième ligne après exists; )
RAM237
3

De toute évidence, il existe un certain nombre de causes possibles et les réponses précédentes les documentent bien, mais voici comment j'ai résolu ce problème dans un cas particulier:

Un de mes élèves a eu ce problème et j'ai failli m'arracher les cheveux en essayant de le comprendre. Il s'est avéré que le fichier n'existait pas, même s'il en avait l'air. Le problème était que Windows 7 était configuré pour «Masquer les extensions de fichiers pour les types de fichiers connus». Cela signifie que si le fichier semble avoir le nom "data.txt", son nom de fichier réel est "data.txt.txt".

J'espère que cela aidera les autres à se sauver des cheveux.

Petehern
la source
Je ne pense pas que ce soit le problème dans mon cas. Comme mentionné dans ma question: "Je peux copier-coller le chemin complet dans la fenêtre" Exécuter "de Windows et le fichier s'ouvre correctement.", Ce qui signifie que le fichier existe réellement.
atsjoo
3

La new Filecommande crée simplement une instance d'un fichier en utilisant le nom de chemin donné. Il ne crée pas réellement de fichier sur le disque dur.

Si tu le dis

File file = new File ("path");
file.exists() 

Cela ne peut retourner vrai que s'il y avait un fichier existant avec le même chemin. Si vous aviez l'intention de rechercher le même fichier déclaré dans la première ligne, vous devrez peut-être l'utiliser de cette façon.

File file = new File ("path");
file.createNewFile();
file.exists();

Maintenant, cela reviendra vrai.

R1234
la source
petite explication: chaque appel au constructeur par l'utilisation d'un nouveau mot-clé crée un objet - comme dans ce cas un objet décrit par Class dont le nom est File! donc pas une instance de File! = descriptors :)
ceph3us
3

Si vous ne voulez pas traiter les appels getAbsoluteFile () chaque fois que vous devez appeler une méthode, vous feriez mieux de créer déjà votre instance de fichier avec un chemin absolu. Cela devrait faire l'affaire:

File file = new File("utilities/data/someTextFile.txt").getAbsoluteFile();

Je suggère de l'entourer d'un bloc try-catch, BTW.

Fran Marzoa
la source
3

Pour généraliser le problème, le problème survient lors de la conversion d'URL / URI en chemins locaux.

Example: URL url = file:/D:/code%20repo%20sample/sample.txt

// To remove url reference
String localPath = url.getPath();  
> /D:/code%20repo%20sample/sample.txt

// Decoding reserved characters in url from hexadecimal to character
URLDecoder.decode(localPath, StandardCharsets.UTF_8.toString()); 
> /D:/code repo sample/sample.txt

J'espère que cela t'aides.

Arun
la source
2

Lorsque ["Masquer les extensions pour les types de fichiers connus."] Est coché, les fenêtres ouvrent "t.txt.txt" lorsque vous tapez "t.txt" dans [explorer] / [exécuter windows] mais pas par programme.

moi aussi
la source
1
J'ai eu ce problème, et le problème était que j'ai créé un fichier txt, qui s'appelait «testFile.txt», dans C: \ test. J'ai fait référence à ce fichier en utilisant le chemin C: \ test \ testFile.txt, qui n'a pas fonctionné. C'était parce que le fichier avait en fait été sauvegardé sous le nom testFile.txt.txt, d'où le vote positif sur la solution ci-dessus (Ancienne question, mais pas de réponse acceptée!)
Theblacknight
Dieu Windows est tellement nul.
aafc
0

Bonnes réponses à tous. J'ai trouvé que cela semble être un problème avec Java pour accéder au C:répertoire racine de Windows. Tout autre répertoire devrait convenir, mais pour une raison quelconque, mentionnant spécifiquement C:\ou C:ou C:/pourrait donner une erreur. J'ai résolu ce problème très similaire en interceptant mention new File("C:");et en le remplaçant par un nouveauFile(System.getProperty("file.separator")); ou vous devriez être capable de coder en dur "\" au lieu de dire "c:" comme répertoire de fichiers et cela pourrait fonctionner. Pas élégant, mais a fait le travail pour moi sur ce projet.

J'espère que cela aide. Ce n'est peut-être pas la bonne solution, mais au moins cela a fonctionné pour moi. Je suis dessusJRE 1.6, Win 7 . À votre santé!

Avec respect,

@ Carpenter1010

Charpentier de code
la source
0

Si les situations où il échoue implique de l'exécuter en tant qu'un autre utilisateur et que vous êtes sous Windows Vista / Windows 7, cela peut être dû à VirtualStore, le mécanisme par lequel Windows laisse un utilisateur non privilégié "écrire" le place qu'il ne peut normalement pas. Les modifications sont cependant stockées dans "% USERPROFILE% \ AppData \ Local \ VirtualStore \" qui sont privés pour chaque compte utilisateur.

Kjetil Joergensen
la source
1
Je cours sous Windows
XP
0

Quand rien d'en haut n'a fonctionné pour moi, j'ai essayé

filePath = filePath.trim();

Cela nettoiera votre chaîne de tout caractère indésirable

Asim
la source
0

Je suis récemment tombé sur le même problème. Ce que j'ai fait, c'est désinstaller Netbeans, le dossier netbeans supprimé du lecteur C, les fichiers de programme, la mise à jour, les données de programme, pratiquement partout. Puis réinstallez. Fonctionne maintenant très bien. N'oubliez pas de sauvegarder le dossier du projet netbeans avant d'effectuer les actions ci-dessus.

J'espère que ça aide.

Evaboy
la source
0

Avec certains IDE (peut-être) et ou avec certains OS (ex: window), par défaut, ils n'ont pas d'accès en écriture sur les fichiers. Donc, si vous essayez de faire file.exists (), il vous montrera false. pour résoudre ce problème, faites comme ci-dessous

si votre variable de référence pour File est f, exemple: File f = new File ("path");

donc pour le faire fonctionner, sélectionnez f à la souris, puis allez dans le menu Recherche> Accès en écriture> Espace de travail. Espérons que cela fonctionnera.

Gautam Anand
la source
-2

Je pense que vous devriez plutôt utiliser une barre oblique inverse, comme ceci:

Fichier fichier = nouveau fichier ("C: \\ User \\ utilities \\ data \\ someTextFile.txt"); (deux contre-obliques, pas une faute de frappe)

Devrait résoudre le problème :)

Hussein Maziad
la source
3
Je pense que le problème est plus lié au chemin absolu qu'au chemin relatif. Les barres obliques sont valides en Java même pour les chemins Windows.
рüффп