2009-10-12 6 views
9

J'essaie de mettre en œuvre l'opération suivante en Java et ne suis pas sûr de savoir comment:comment créer un fichier en Java seulement s'il n'en existe pas déjà?

/* 
* 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 
    } 
} 

Y at-il une fonction qui existe déjà que je peux utiliser pour atomicCreateFile()?

edit: Euh oh, je ne suis pas sûr que File.createNewFile() soit suffisant pour mes besoins. Que faire si j'appelle f.createNewFile() et puis entre le moment où il revient et j'ouvre le fichier pour l'écriture, quelqu'un d'autre a supprimé le fichier? Est-il possible de créer le fichier et de l'ouvrir pour l'écrire + le verrouiller, d'un seul coup? Ai-je besoin de m'inquiéter à ce sujet?

Répondre

18

File.createNewFile() crée uniquement un fichier s'il n'en existe pas déjà un.

EDIT: Selon votre nouvelle description de vouloir verrouiller le fichier après sa création, vous pouvez utiliser l'objet java.nio.channels.FileLock pour verrouiller le fichier. Il n'y a pas une seule ligne de création et de verrouillage bien que vous espériez. Voir aussi SO question.

+0

doh! comment ai-je manqué ça? :/ Merci. Mon esprit a été en terre C++. –

+0

mis à jour ma réponse basée sur votre édition –

+0

ok, merci. Eh bien, il semble que je dois réfléchir soigneusement aux conditions exceptionnelles. (par exemple.si le createNewFile() réussit mais ouvre un canal de fichier et obtient un verrou de fichier échoue) –

7

File.createNewFile()

atomiquement crée un nouveau fichier vide nommé par ce chemin abstrait si et seulement si un fichier avec ce nom n'existe pas encore. La vérification de l'existence du fichier et de la création du fichier s'il n'existe pas est une opération unique qui est atomique par rapport à toutes les autres activités du système de fichiers susceptibles d'affecter le fichier.

EDIT

Jason, comme pour votre souci, si vous continuez à lire le lien que nous vous avons envoyé il y a une note à ce sujet.

Note: cette méthode ne doit pas être utilisé pour le fichier-verrouillage, le protocole résultant ne peut pas être fait pour fonctionner de manière fiable. L'installation FileLock doit être utilisée à la place.

Je pense que vous devriez vraiment lire cette partie aussi:

alt

+0

Joachim: Aucun problème, utilise donc le verrou optimiste pour l'édition – OscarRyz

+0

Merci, j'ai lu la note, c'est ce qui a déclenché le Uh oh. –

+0

(Malheureusement, il ne semble pas y avoir de référentiel de paradigmes d'E/S Java, en plus d'explorer manuellement la plate-forme javadocs, qui dit que ce sont tous les outils disponibles ... File et FileLock sont dans des paquets complètement différents, parfois vous utilisez FileChannel, parfois vous utilisez FileOutputStream ... fait parfois tourner la tête.) –

-1

Pourquoi ne pouvez-vous tester à l'aide File#exists?

+6

car entre le moment où vous testez en utilisant File.exists(), et vous allez créer un fichier s'il n'existe pas, quelqu'un d'autre aurait pu créer le fichier en premier. –

+5

Parce que entre le temps 'exists()' renvoie false et il construit le 'FileOutputStream' un autre processus pourrait sauter et créer le fichier. Une condition de course classique. –

+18

(de la même façon que j'ai glissé dans ce commentaire juste devant Joachim. :-) –

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

J'ai changé le paramètre pour le constructeur de fichier à une chaîne réelle dans le cas où il échouait. – cosbor11

+0

Lorsque le système crée un fichier, il aura un pseudo "lock". – cosbor11

+0

Lorsque vous écrivez dans le fichier, il doit également obtenir un handle sur l'objet File afin qu'aucun autre thread ne puisse y accéder ou le supprimer. Vous pouvez écrire un test JUnit pour le confirmer. Si vous rencontrez des problèmes, vous pouvez exécuter vos opérations dans un bloc synconized() {}. – cosbor11

2

version Java 7 avec Files#createFile:

Path out; 

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