如何在Java中创建一个文件,只有当该文件不存在时才创建?

10

我正在尝试在Java中实现以下操作,但不确定如何实现:

/*
 * write data (Data is defined in my package)
 * to a file only if it does not exist, return success
 */
boolean writeData(File f, Data d)
{
    FileOutputStream fos = null;
    try 
    {
        fos = atomicCreateFile(f);
        if (fos != null)
        {
            /* write data here */
            return true;
        }
        else
        {
            return false;
        }
    }
    finally
    {
        fos.close();  // needs to be wrapped in an exception block
    }
}

是否已经存在现有的函数可供使用 atomicCreateFile()

编辑:糟糕,我不确定 File.createNewFile() 是否满足我的需求。如果我调用 f.createNewFile(),然后在返回和打开文件进行写操作之间,有人删除了该文件怎么办?是否有一种方法可以一次性创建文件、打开它进行写操作并锁定它?我需要担心这个问题吗?

5个回答

20

糟糕!我怎么会错过那个?:/ 谢谢。我的思维一直在C++的世界里。 - Jason S
好的,谢谢。听起来我需要仔细考虑异常情况。(例如,如果createNewFile()成功但打开文件通道和获取文件锁失败) - Jason S

8

File.createNewFile()

如果该抽象路径名表示的文件名不存在,则原子性地创建一个新的空文件。检查文件是否存在以及在文件不存在时创建文件是单个操作,与可能影响文件的所有其他文件系统活动一起具有原子性。

编辑

关于您的担忧,如果您继续阅读我们发送给您的链接,那里有一个关于此方法的注意事项

注意: 该方法不应用于文件锁定,因为无法使得生成的协议可靠工作。应使用FileLock 工具。

我认为您也应该仔细阅读这部分内容:

alt


谢谢,我已经看了注意事项,这就是触发“Uh oh”的原因。 - Jason S
很遗憾,除了手动浏览平台javadocs以外,好像没有Java I/O范例的存储库说这些都是你可以使用的工具......File和FileLock在完全不同的包中,有时你会使用FileChannel,有时你会使用FileOutputStream......有时会让我的头晕。 - Jason S
我也找到了那个,但我并不是将文件用作锁定,我只是想要确保如果我写入文件,我是第一个这样做的人,并且在我写入文件时没有其他人触碰它。 - Jason S

2

使用Files#createFile创建Java 7版本中的文件:

Path out;

try {
    out = Files.createFile(Paths.get("my-file.txt"));
} catch (FileAlreadyExistsException faee) {
    out = Paths.get("my-file.txt");
}

-1

6
因为在你使用File.exists()测试文件是否存在的时间和创建文件(如果它不存在)的时间之间,其他人可能已经先创建了这个文件。 - Jason S
5
因为在exists()返回false和构造FileOutputStream之间,另一个进程可能会介入并创建该文件。这是一种经典的竞态条件。 - Joachim Sauer
19
(我)就像在乔阿希姆之前悄悄地加了那个评论一样。 - Jason S
3
确实是出色的演示,;-) - Joachim Sauer

-2
//myFile should only be created using this method to ensure thread safety
public synchronized File getMyFile(){
  File file = new File("path/to/myfile.ext");
  if(!file.exists()){
     file.getParentFile().mkdirs();
     file.createNewFile();
  }
  return file;
}  

我将File构造函数的参数更改为实际字符串,以防它失败。 - cosbor11
当系统创建文件时,它将在其上拥有一个句柄,也称为“锁定”。 - cosbor11
当您写入文件时,它还应该获取文件对象的句柄,以便其他线程无法访问或删除它。您可以编写一个 JUnit 测试来确认这一点。如果遇到任何问题,您可以在 synchronized(){} 块中运行操作。 - cosbor11
阅读Geo的回答以及相关评论。 - Jason S
这个文件是单例模式吗?如果是的话,我会将方法同步,这样只有一个线程可以同时访问它。 - cosbor11
我本想在另一个回答中写出另一个代码示例,但我担心您会再次扣除我的声望分数 - 因此,我认为我会远离这篇帖子,因为要求并不是非常明确定义的。 - cosbor11

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接