【问题标题】:Cannot delete temp folder (sometimes)无法删除临时文件夹(有时)
【发布时间】:2011-07-12 11:03:45
【问题描述】:

当我启动我的应用程序时,我会创建一个临时文件夹:

  public static File createTempDir(String name) throws IOException {
    File tempDir = File.createTempFile(name, "");
    if (!(tempDir.delete())) {
      throw new IOException("could not delete" + tempDir.getAbsolutePath());
    }

    if (!(tempDir.mkdir())) {
      throw new IOException("could not create" + tempDir.getAbsolutePath());
    }
    tempDir.deleteOnExit();
    return tempDir;
  }

在会话期间,用户可能会加载文件。结果,旧的临时目录被删除,并根据加载的文件的 ID 创建了一个新目录。

在删除旧临时目录的加载过程中,我有时会收到:

java.io.IOException:无法删除文件:

以下是删除旧临时文件夹的方法:

  public void cleanup(String tmpPath) {
    File tmpFolder = new File(tmpPath);
    if (tmpFolder != null && tmpFolder.isDirectory()) {
      try {
        FileUtils.deleteDirectory(file);
      } catch (IOException e) {
            e.printStackTrace();
      }
    } 
  }

FileUtils 在哪里:org.apache.commons.io.FileUtils。通常临时文件夹的内容是:

mytempfolder_uuid |-> 我的子文件夹 |-> myImage.jpg

错误是:

java.io.IOException:无法删除文件:C:\Users\xxx\AppData\Local\Temp\mytempfolder_uuid\mysubfolder\myImage.jpg

我已尝试调试应用程序,在执行删除操作之前验证上述图像实际上位于指定文件夹中。

令人讨厌的是,它只是偶尔发生。我已确保不要在任何其他应用程序中打开临时文件夹中的文件夹/文件。有什么想法/建议吗?

【问题讨论】:

  • 也许您忘记在应用程序的某个位置关闭该文件的流?
  • 当您尝试删除时,可能有人(用户、应用程序)有时会使用该文件夹。
  • @tul,您有近 30 个问题没有得到接受的答案。也许您可以尝试提出可以合理回答的问题或跟进答案,以便他们可以接受。 ;)

标签: java io


【解决方案1】:

您不能删除打开的文件,也不能删除包含文件的目录。您必须确保目录中的所有文件都已关闭。

【讨论】:

  • 据我了解 org.apache.commons.io.FileUtils.deleteDirectory(file) 递归删除文件夹。是否可以从 java 代码中获取引用特定文件/文件夹的进程列表?
  • 您可以在 Unix 中使用 lsof。很可能是您的进程打开了文件。尤其是如果它们是临时文件。
【解决方案2】:

我建议你使用 Guava 库。它有一个方法 Files.createTempDir() 可以完全满足您的需求:

在系统目录下的某处自动创建一个新目录 临时目录(由 java.io.tmpdir 系统定义) 属性),并返回其名称。使用此方法代替 File.createTempFile(String, String) 当你想创建一个 目录,而不是常规文件。 一个常见的陷阱是调用 createTempFile,删除文件并在其位置创建一个目录, 但这会导致竞争条件,可以利用它来创建 安全漏洞,尤其是当可执行文件是 写入目录。此方法假定临时 卷是可写的,有空闲的 inode 和空闲的块,它会 每秒不会被调用数千次。

【讨论】:

  • 好的,谢谢你的提示,我会试试看!我真的需要这是确定性的。目前,即使我执行完全相同的步骤(保存/加载相同的文件夹/文件)似乎非常随机,它有时也只能工作。
  • 好的,我尝试用番石榴替换我的实现,但我的问题仍然存在。出于某种原因,临时目录中的文件(image.jpg)在我运行测试的一半时间不能被删除 - 另一半工作正常。必须是某些资源在删除之前拥有或未正确处理。
  • @tul 是的,确保在 finally 块中关闭所有流(输入和输出)。你可能想看看Closeables
  • 基本上我只是在按钮上设置了一个 org.eclipse.swt.graphics.Image.Image,例如: myImage = new Image(getDisplay(), new ImageData(absolutePath)); button.setImage(myImage);在进行加载之前,我确保容器小部件已关闭并且所有子小部件/图像都已处理。但仍然困扰我的是它只有 50% 的机会发生。
  • @tul 无法帮助您处理 SWT。您应该使用 SWT 标签在另一个问题中询问该部分
【解决方案3】:

在删除之前尝试删除临时文件夹中的文件。尝试类似

private boolean deleteFolder(File path) {
    if (path.exists()) {
        File[] files = path.listFiles();
        for (File f : files) {
            if (f.isDirectory()) {
                deleteFolder(f);
            } else {
                f.delete();
            }
        }
    }

    return path.delete();
}

也使用 deleteOnExit 不是一个好主意...

干杯!

【讨论】:

  • 但这正是 org.apache.commons.io.FileUtils.deleteDirectory(file) 所做的。我需要 deleteOnExit,因为我不希望临时目录变得异常大 - 你还怎么执行清理?
  • deleteOnExit 不会帮助您将临时目录保持在最小大小。如果你想这样做,你可以编写一个简单的线程来监视 dirs 大小并在大小超过某个阈值时将其删除。或者,如果您使用的是 apache commons,则可以安装 FileMonitor 来监视目录...使用 deleteOnExit 是不好的,因为它会泄漏内存并且不能保证它会成功。
  • 是的,deleteOnExit 似乎只适用于空文件夹:-(
【解决方案4】:
public static boolean deleteDir(String path)
{
    java.io.File dir = new java.io.File(path);
    if (dir.isDirectory())
    {
        String[] filesList = dir.list();
        for(String s : filesList)
        {
            boolean success = new java.io.File(dir, s).delete();
            if(!success)
            {
                return false;
            }
        }
    }
    return dir.delete();
}

然后你可以像这样使用它:deleteDir("C:\\MyFolder\\subFolder\\")

【讨论】:

  • 我相信这基本上就是 org.apache.commons.io.FileUtils.deleteDirectory(file) 所做的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-13
  • 1970-01-01
相关资源
最近更新 更多