即使 file.exists()、file.canRead()、file.canWrite()、file.canExecute() 都返回 true,file.delete() 返回 false

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

  •  13-09-2019
  •  | 
  •  

我正在尝试删除一个文件,在其中写入一些内容后, FileOutputStream. 。这是我用来编写的代码:

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();
    }
}

正如所见,我刷新并关闭流,但是当我尝试删除时, file.delete() 返回假。

我在删除之前检查了该文件是否存在,并且: file.exists(), file.canRead(), file.canWrite(), file.canExecute() 全部返回 true。调用这些方法后我尝试 file.delete() 并返回 false。

我是不是做错了什么?

有帮助吗?

解决方案 2

这是很奇怪的是,工作的伎俩。问题是,当我以前读取文件的内容,我用BufferedReader。看完后,我封闭缓冲液。

同时我切换,现在我使用FileInputStream读取内容。此外读完后,我关闭流。现在,它的工作。

问题是我没有这样做的解释。

不知BufferedReaderFileOutputStream是不相容的。

其他提示

在Java中的另一种错误。我很少看到他们,只有我在我的10年职业生涯第二。这是我的解决方案,正如其他人提及。我有幽冥使用System.gc()。但是在这里,在我而言,这是绝对至关重要的。奇怪的? YES!

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

我想这个简单的事情,它似乎是工作。

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

这对我的作品。

如果这不起作用尝试,如果在Linux上,并以管理员身份运行使用sudo你的Java应用程序在Windows上的时候。只是为了确保Java有权利更改文件属性。

试图删除/重命名的任何文件之前,你必须确保所有的读者和作家(为前:BufferedReader / InputStreamReader / BufferedWriter)。正确关闭

当您尝试读取/从/到一个文件,该文件是由进程持有,而不是释放,直到程序运行结束写入数据。如果要执行删除/重命名操作的全部程序结束之前,则必须使用随附close()java.io.*方法。

由于乔恩斯基特评论,应关闭文件中的最后{...}块,以确保它总是关闭。并且,而不是吞咽与e.printStackTrace例外,根本就没有抓住他,除了添加到方法签名。如果你不能以任何理由,至少做到这一点:

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

现在,问题是#2:

如果你这样做是什么:

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

您是否能够删除文件?

此外,文件被刷新时,他们关闭。我用IOUtils.closeQuietly(...),所以我用的冲洗方法,以确保文件的内容是否有之前我尝试关闭它(IOUtils.closeQuietly不抛出异常)。是这样的:

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

所以我知道该文件的内容都在里面。因为它通常与我有关,该文件的内容写入,而不是如果该文件可能被关闭或没有,真的没有,如果该文件被关闭或没有关系。根据你的情况,因为它很重要,我会建议你自己关闭文件,并根据处理任何异常。

有没有理由,你不应该能够删除这个文件。我想看看,看看谁对这个文件保持。在Unix / Linux操作系统,你可以使用lsof工具来检查哪个进程在文件上的锁。在窗口中,可以使用过程资源管理器。

有lsof的,这是简单的话说:

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

有关进程管理器,你可以使用查找菜单,然后输入文件名给你看,这将指向你的过程中锁定该文件句柄。

下面是一些代码,做什么,我认为你需要做的:

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();
}

它的工作原理在OS X罚款我没有测试它在Windows,但我怀疑它应该在Windows上工作了。我也得承认看到在Windows w.r.t.一些意想不到的行为文件处理。

如果您在Eclipse IDE中工作,这可能意味着你没有关闭该文件在以前启动该应用程序。当我有相同的错误消息在试图删除文件,这是原因。看来,Eclipse IDE中不关闭所有文件的应用程序终止后。

希望这将有助于。我碰到类似的问题在那里后,我的Java代码进行的内容的副本到其他文件夹我无法删除我的文件。广泛的谷歌搜索后,我明确宣布的每一个文件操作有关的变量,并呼吁每个文件操作对象的close()方法,并将其设置为NULL。然后,有一个叫System.gc()的函数,这将清理文件I / O映射(我不知道,我只是告诉什么是对网站给出)。

下面是我的示例代码:

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();
    }
}

答案是,当你加载的文件,你需要应用“亲密”的方法,在任何一行代码,工作对我

写它,并关闭它后

在红宝石在需要在Windows中的文件的“FSYNC”居然能扭亏为盈,并有一个问题,一旦重新读取该文件。也许这是一个类似的表现(如果有的话,我觉得窗户错误,真的)。

下面列出了我的处境工作的解决方案都不是。我的解决方案是使用一个while循环,试图删除该文件,以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--;
}

使用上述循环工作而无需做任何手动垃圾收集或设置流为空,等等。

在问题可能是该文件仍然被视为打开和通过程序来锁定;或者它是从你的,它一直在打开的程序组件,所以你必须确保你使用dispose()方法来解决这个问题。 即JFrame frame; .... frame.dispose();

您必须关闭所有的流或使用try-与资源块

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;
}

如果file.delete()被发送伪造的,然后在你的大部分的BufferedReader手柄不会被关闭的情况。只是关闭它似乎为我正常工作。

我在Windows同样的问题。我用于读取与

在由线阶行的文件
Source.fromFile(path).getLines()

现在我读它作为一个整体与

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

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

其中阅读和现在适当后关闭该文件

new File(path).delete

作品。

  

有关的Eclipse / NetBeans的

重新启动IDE并运行代码这同样是一小时后的长期斗争,我只招工作。

下面是我的代码:

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

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

<强>输出:

删除

另一个可能发生这种情况的极端情况:如果您通过a读取/写入JAR文件 URL 然后尝试在同一个 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!

原因是Java内部JAR文件处理逻辑,倾向于缓存 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();
            }
        }
    }
}

还有每一个 JarFile (相反,底层 ZipFile 结构)将保存文件的句柄,从构建时一直到 close() 被调用:

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;

有一个很好的解释 这个 NetBeans 问题.


显然有两种方法可以“解决”这个问题:

  • 您可以禁用 JAR 文件缓存 - 对于当前的 URLConnection, ,或者对于所有的未来 URLConnection当前 JVM 会话中的 s(全局):

    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);
    
  • [黑客警告!] 您可以手动清除 JarFile 当你完成后从缓存中取出。缓存管理器 sun.net.www.protocol.jar.JarFileFactory 是包私有的,但是一些反射魔法可以为您完成工作:

    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.
    

请注意: 所有这一切都基于 Java 8 代码库(1.8.0_144);它们可能无法与其他/更高版本一起使用。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top