fichier.delete() renvoie la valeur false, même si fichier.exists(), fichier.canRead(), le fichier.canWrite(), le fichier.canExecute() toutes return true

StackOverflow https://stackoverflow.com/questions/991489

  •  13-09-2019
  •  | 
  •  

Question

Je suis en train de supprimer un fichier, après avoir écrit quelque chose en elle, avec FileOutputStream.C'est le code que j'utilise pour écrire:

private void writeContent(File file, String fileContent) {
    FileOutputStream to;
    try {
        to = new FileOutputStream(file);
        to.write(fileContent.getBytes());
        to.flush();
        to.close();
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

Comme on le voit, je tire la chasse et de fermer le flux de données, mais lorsque je tente de supprimer, file.delete() renvoie la valeur false.

J'ai vérifié avant la suppression de voir si le fichier existe, et: file.exists(), file.canRead(), file.canWrite(), file.canExecute() tous les renvoie la valeur true.Juste après l'appel de ces méthodes j'essaie file.delete() et renvoie la valeur false.

Est-il rien de ce que j'ai fait de mal?

Était-ce utile?

La solution 2

Il a été le truc qui fonctionnait assez bizarre. La chose est quand je l'ai déjà lu le contenu du fichier, je BufferedReader. Après la lecture, j'ai fermé la mémoire tampon.

Pendant ce temps je suis passé et maintenant je lis le contenu en utilisant FileInputStream. Aussi après avoir terminé la lecture je ferme le flux. Et maintenant, il travaille.

Le problème est que je n'ai pas pour cette explication.

Je ne sais pas BufferedReader et FileOutputStream incompatibles.

Autres conseils

Un autre bogue dans Java. Je les trouve rarement, seulement ma deuxième dans ma carrière de 10 ans. Ceci est ma solution, comme d'autres l'ont mentionné. J'ai Nether utilisé System.gc(). Mais ici, dans mon cas, il est absolument crucial. Bizarre? OUI!

finally
{
    try
    {
        in.close();
        in = null;
        out.flush();
        out.close();
        out = null;
        System.gc();
    }
    catch (IOException e)
    {
        logger.error(e.getMessage());
        e.printStackTrace();
    }
}

J'ai essayé cette chose simple et il semble fonctionner.

file.setWritable(true);
file.delete();

Il fonctionne pour moi.

Si cela ne fonctionne pas essayer d'exécuter votre application Java avec sudo si sur linux et en tant qu'administrateur lorsque les fenêtres. Juste pour vous assurer Java a le droit de modifier les propriétés du fichier.

Avant d'essayer de supprimer / renommer un fichier, vous devez vous assurer que tous les lecteurs ou écrivains (pour ex: BufferedReader / InputStreamReader / BufferedWriter). Sont bien fermés

Lorsque vous essayez de lire / écrire vos données depuis / vers un fichier, le fichier est tenu par le processus et non libéré jusqu'à ce que l'exécution du programme se termine. Si vous souhaitez effectuer la suppression / renommer des opérations avant la fin du programme, vous devez utiliser la méthode close() qui vient avec les classes java.io.*.

Jon Skeet a commenté, vous devez fermer votre fichier dans le bloc finally {...}, pour vous assurer qu'il est toujours fermé. Et, au lieu d'avaler les exceptions avec le e.printStackTrace, il suffit de ne pas attraper et ajouter l'exception à la signature de la méthode. Si vous ne pouvez pas pour une raison quelconque, au moins faire ceci:

catch(IOException ex) {
    throw new RuntimeException("Error processing file XYZ", ex);
}

, le numéro de la question n ° 2:

Et si vous faites ceci:

...
to.close();
System.out.println("Please delete the file and press <enter> afterwards!");
System.in.read();
...

Seriez-vous capable de supprimer le fichier?

En outre, les fichiers sont vidées quand ils sont fermés. J'utilise IOUtils.closeQuietly (...), donc j'utilise la méthode flush pour faire en sorte que le contenu du fichier sont là avant que j'essaie de le fermer (IOUtils.closeQuietly ne jette pas des exceptions). Quelque chose comme ceci:

...
try {
    ...
    to.flush();
} catch(IOException ex) {
    throw new CannotProcessFileException("whatever", ex);
} finally {
    IOUtils.closeQuietly(to);
}

Je sais que le contenu du fichier sont là-dedans. Comme il importe généralement pour moi que le contenu du fichier sont écrits et non si le fichier peut être fermé ou non, il n'a pas d'importance si le dossier a été fermé ou non. Dans votre cas, comme il importe, je recommande de fermer le fichier vous-même et le traitement des exceptions selon.

Il n'y a aucune raison que vous ne devriez pas être en mesure de supprimer ce fichier. Je regarderais pour voir qui a une emprise sur ce fichier. Dans unix / linux, vous pouvez utiliser l'utilitaire lsof pour vérifier quel processus a un verrou sur le fichier. Dans Windows, vous pouvez utiliser l'explorateur de processus.

lsof, il est aussi simple que de dire:

lsof /path/and/name/of/the/file

pour explorer processus, vous pouvez utiliser le menu Rechercher et saisissez le nom du fichier pour vous montrer la poignée qui vous dirigera vers le processus de verrouillage du fichier.

ici est un code qui fait ce que je pense que vous devez faire:

FileOutputStream to;

try {
    String file = "/tmp/will_delete.txt";
    to = new FileOutputStream(file );
    to.write(new String("blah blah").getBytes());
    to.flush();
    to.close();
    File f = new File(file);
    System.out.print(f.delete());
} catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

Il fonctionne très bien sur OS X. Je ne l'ai pas testé sur Windows, mais je suppose que cela devrait fonctionner sur Windows aussi. Je dois admettre aussi voir des comportements inattendus sur Windows w.r.t. la gestion des fichiers.

Si vous travaillez dans Eclipse IDE, cela pourrait signifier que vous ne fermez le fichier dans le lancement de l'application précédente. Quand j'ai eu le même message d'erreur à essayer de supprimer un fichier, qui était la raison. Il semble, Eclipse IDE ne se ferme pas tous les fichiers après la fin d'une application.

Espérons que cela vous aidera. Je suis tombé sur le même problème où je ne pouvais pas supprimer mon fichier après mon code java fait une copie du contenu à l'autre dossier. Après des recherches sur Google, je déclarai explicitement chaque opération fichier unique variables liées et a appelé la méthode close () de chaque objet d'opération de fichier, et les mises à NULL. Ensuite, il y a une fonction appelée System.gc (), qui effacera le fichier i / o la cartographie (je ne suis pas sûr, je viens de dire ce qui est donné sur les sites Web).

Voici mon exemple de code:

public void start() {
    File f = new File(this.archivePath + "\\" + this.currentFile.getName());
    this.Copy(this.currentFile, f);

    if(!this.currentFile.canWrite()){
        System.out.println("Write protected file " +
           this.currentFile.getAbsolutePath());

        return;
    }


    boolean ok = this.currentFile.delete();
    if(ok == false){
        System.out.println("Failed to remove " + this.currentFile.getAbsolutePath());
        return;
    }
}

private void Copy(File source, File dest) throws IOException {
    FileInputStream fin;
    FileOutputStream fout;
    FileChannel cin = null, cout = null;
    try {
        fin = new FileInputStream(source);
        cin = fin.getChannel();
        fout = new FileOutputStream(dest);
        cout = fout.getChannel();

        long size = cin.size();
        MappedByteBuffer buf = cin.map(FileChannel.MapMode.READ_ONLY, 0, size);

        cout.write(buf);
        buf.clear();
        buf = null;

        cin.close();
        cin = null;

        fin.close();
        fin = null;

        cout.close();
        cout = null;

        fout.close();
        fout = null;

        System.gc();

    } catch (Exception e){
        this.message = e.getMessage();
        e.printStackTrace();
    }
}

la réponse est lorsque vous chargez le fichier, vous devez appliquer la méthode « fermer », dans une ligne de code, fonctionne à moi

Il y avait un problème une fois en ruby où les fichiers dans windows besoin d'un "fsync" d'être capable de tourner autour et de re-lire le fichier après l'avoir écrit et de fermeture.C'est peut-être une manifestation similaire (et si oui, je pense que windows bug, vraiment).

Aucune des solutions présentées ici travaillées dans ma situation. Ma solution a été d'utiliser une boucle de temps, la tentative de supprimer le fichier, avec une limite de sécurité de deuxième (configurable) 5.

File f = new File("/path/to/file");

int limit = 20; //Only try for 5 seconds, for safety
while(!f.delete() && limit > 0){
    synchronized(this){
        try {
            this.wait(250); //Wait for 250 milliseconds
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    limit--;
}

Utilisation de la boucle ci-dessus a fonctionné sans avoir à effectuer une collecte de déchets manuel ou régler le courant à vide, etc.

Le problème pourrait être que le fichier est toujours considéré comme ouvert et verrouillé par un programme; ou peut-être est un élément de votre programme qu'il avait été ouvert, donc vous devez vous assurer que vous utilisez la méthode dispose() pour résoudre ce problème. à savoir JFrame frame; .... frame.dispose();

Vous devez fermer tous les cours d'eau ou utiliser essayer avec bloc-ressources

static public String head(File file) throws FileNotFoundException, UnsupportedEncodingException, IOException
{
    final String readLine;
    try (FileInputStream fis = new FileInputStream(file);
            InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
            LineNumberReader lnr = new LineNumberReader(isr))
    {
        readLine = lnr.readLine();
    }
    return readLine;
}

si File.Delete () envoie alors faux dans la plupart des cas, votre poignée BufferedReader ne sera pas fermée. Tout près et il semble fonctionner pour moi normalement.

J'ai eu le même problème sur Windows. Je l'habitude de lire le fichier en ligne scala par ligne avec

Source.fromFile(path).getLines()

Maintenant, je l'ai lu dans son ensemble avec

import org.apache.commons.io.FileUtils._

// encoding is null for platform default
val content=readFileToString(new File(path),null.asInstanceOf[String])

qui ferme le fichier correctement après avoir lu et maintenant

new File(path).delete
travaux

.

  

Eclipse / NetBeans

Redémarrez votre IDE et exécutez votre code à nouveau c'est que le travail de truc pour moi après une heure longue lutte.

Voici mon code:

File file = new File("file-path");
if(file.exists()){
  if(file.delete()){
     System.out.println("Delete");
  }
  else{

       System.out.println("not delete");
  }
}

Sortie:

Supprimer

Un autre cas de coin que cela pourrait se produire. Si vous lisez / écrivez un fichier JAR par un URL et essayer plus tard supprimer le même fichier dans la même session JVM

File f = new File("/tmp/foo.jar");
URL j = f.toURI().toURL();

URL u = new URL("jar:" + j + "!/META-INF/MANIFEST.MF");
URLConnection c = u.openConnection();

// open a Jar entry in auto-closing manner
try (InputStream i = c.getInputStream()) {

    // just read some stuff; for demonstration purposes only
    byte[] first16 = new byte[16];
    i.read(first16);
    System.out.println(new String(first16));
}

// ...

// i is now closed, so we should be good to delete the jar; but...
System.out.println(f.delete());     // says false!

La raison est que la logique de gestion des fichiers JAR de Java interne, tend à mettre en cache les entrées de JarFile:

// inner class of `JarURLConnection` that wraps the actual stream returned by `getInputStream()`

class JarURLInputStream extends FilterInputStream {
    JarURLInputStream(InputStream var2) {
        super(var2);
    }

    public void close() throws IOException {
        try {
            super.close();
        } finally {

            // if `getUseCaches()` is set, `jarFile` won't get closed!

            if (!JarURLConnection.this.getUseCaches()) {
                JarURLConnection.this.jarFile.close();
            }
        }
    }
}

Et chaque JarFile (plutôt, la structure sous-jacente ZipFile) détiendrait une poignée dans le fichier, depuis le temps jusqu'à la construction jusqu'à ce que close() est invoqué:

public ZipFile(File file, int mode, Charset charset) throws IOException {
    // ...

    jzfile = open(name, mode, file.lastModified(), usemmap);

    // ...
}

// ...

private static native long open(String name, int mode, long lastModified,
                                boolean usemmap) throws IOException;

Il y a une bonne explication sur cette question NetBeans .


Apparemment, il y a deux façons de « fixer »:

  • Vous pouvez désactiver la mise en cache de fichiers JAR - pour le URLConnection en cours ou pour tous les futurs URLConnections (globalement) dans la session JVM actuelle:

    URL u = new URL("jar:" + j + "!/META-INF/MANIFEST.MF");
    URLConnection c = u.openConnection();
    
    // for only c
    c.setUseCaches(false);
    
    // globally; for some reason this method is not static,
    // so we still need to access it through a URLConnection instance :(
    c.setDefaultUseCaches(false);
    
  • [HACK AVERTISSEMENT!] Vous pouvez purger manuellement le JarFile à partir du cache lorsque vous avez terminé avec elle. Le gestionnaire de cache est sun.net.www.protocol.jar.JarFileFactory package-privé, mais la magie de réflexion peut faire le travail pour vous:

    class JarBridge {
    
        static void closeJar(URL url) throws Exception {
    
            // JarFileFactory jarFactory = JarFileFactory.getInstance();
            Class<?> jarFactoryClazz = Class.forName("sun.net.www.protocol.jar.JarFileFactory");
            Method getInstance = jarFactoryClazz.getMethod("getInstance");
            getInstance.setAccessible(true);
            Object jarFactory = getInstance.invoke(jarFactoryClazz);
    
            // JarFile jarFile = jarFactory.get(url);
            Method get = jarFactoryClazz.getMethod("get", URL.class);
            get.setAccessible(true);
            Object jarFile = get.invoke(jarFactory, url);
    
            // jarFactory.close(jarFile);
            Method close = jarFactoryClazz.getMethod("close", JarFile.class);
            close.setAccessible(true);
            //noinspection JavaReflectionInvocation
            close.invoke(jarFactory, jarFile);
    
            // jarFile.close();
            ((JarFile) jarFile).close();
        }
    }
    
    // and in your code:
    
    // i is now closed, so we should be good to delete the jar
    JarBridge.closeJar(j);
    System.out.println(f.delete());     // says true, phew.
    

S'il vous plaît noter: Tout cela est basé sur Java 8 codebase (1.8.0_144); ils ne peuvent pas travailler avec d'autres / les versions ultérieures.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top