323 votes

Comment créer un fichier temporaire avec une extension spécifique avec .net ?

Je dois générer un fichier temporaire unique avec une extension .csv.

Ce que je fais en ce moment est

string filename = System.IO.Path.GetTempFileName().Replace(".tmp", ".csv");

Toutefois, cela ne garantit pas que mon fichier .csv sera unique.

Je sais que les chances d'avoir une collision sont très faibles (surtout si l'on considère que je ne supprime pas les fichiers .tmp), mais ce code ne me semble pas bon.

Bien sûr, je pourrais générer manuellement des noms de fichiers aléatoires jusqu'à ce que je trouve un nom unique (ce qui ne devrait pas poser de problème), mais je suis curieux de savoir si d'autres personnes ont trouvé un moyen efficace de résoudre ce problème.

5 votes

Quelques mises en garde concernant GetTempFileName La méthode GetTempFileName lève une IOException si elle est utilisée pour créer plus de 65535 fichiers sans supprimer les fichiers temporaires précédents. La méthode GetTempFileName déclenche une exception IOException si aucun nom de fichier temporaire unique n'est disponible. Pour résoudre cette erreur, supprimez tous les fichiers temporaires inutiles.

2 votes

Les fichiers temporaires sont principalement utilisés pour un ensemble de conditions spécifiques. Si l'extension du fichier est importante, je me demande si l'utilisation du GetTempFileName n'est pas la solution d'écriture. Je sais que cela fait longtemps, mais si vous nous en disiez plus sur le contexte et le besoin de ces fichiers, nous pourrions être en mesure de vous suggérer une meilleure approche. plus ici : support.microsoft.com/kb/92635?wa=wsignin1.0

1 votes

Gardez à l'esprit GetTempFileName() crée un nouveau fichier à chaque fois que vous l'appelez. -- Si vous changez immédiatement la chaîne de caractères en quelque chose d'autre, vous venez de créer un nouveau fichier de zéro octet dans votre répertoire temporaire (et comme d'autres l'ont noté, cela provoquera éventuellement un échec lorsque vous atteindrez 65535 fichiers dans ce répertoire...) -- Pour éviter cela, assurez-vous de supprimer tous les fichiers que vous créez dans ce répertoire (y compris ceux renvoyés par la commande GetTempFileName() idéalement dans un bloc final).

418voto

Mitch Wheat Points 169614

Garantie d'être (statistiquement) unique :

string fileName = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".csv";

(Pour citer l'article de wiki sur la probabilité d'une collision :

...le risque annuel d'être frappé par une voiture. météorite est estimé à une chance chance sur 17 milliards [19], ce qui veut dire que la probabilité est d'environ 0,00000000006 (6 × 10-11), ce qui équivaut à la probabilité de de créer quelques dizaines de trillions de UUID en un an et d'avoir un seul double. duplicata. En d'autres termes, ce n'est qu'après avoir générer 1 milliard d'UUID chaque seconde pendant les 100 prochaines années, la probabilité de créer un seul duplicata serait d'environ 50%. Le site probabilité d'un duplicata serait d'environ 50% si chaque personne sur terre possède 600 millions d'UUIDs

EDIT : Veuillez également consulter les commentaires de JaredPar.

34 votes

Mais il n'est pas garanti qu'il soit dans un emplacement accessible en écriture.

5 votes

System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".csv" fonctionnera. @Mitch : pourriez-vous mettre à jour votre réponse avant que je ne la marque comme acceptée ? merci.

35 votes

Et ils sont no Il n'est pas du tout garanti qu'il soit unique, juste statistiquement improbable.

67voto

JaredPar Points 333733

Essayez cette fonction ...

public static string GetTempFilePathWithExtension(string extension) {
  var path = Path.GetTempPath();
  var fileName = Guid.NewGuid().ToString() + extension;
  return Path.Combine(path, fileName);
}

Il renverra un chemin complet avec l'extension de votre choix.

Notez qu'il n'est pas garanti de produire un nom de fichier unique puisque quelqu'un d'autre pourrait techniquement avoir déjà créé ce fichier. Cependant, les chances que quelqu'un devine le prochain guid produit par votre application et le crée sont très très faibles. Il est assez sûr de supposer qu'il sera unique.

4 votes

Peut-être que Path.ChangeExtension() serait plus élégant que Guid.NewGuid().ToString() + extension

1 votes

@ohadsc - en effet, Guid.NewGuid().ToString() + extension n'est même pas correcte, elle devrait être Guid.NewGuid().ToString() + "." + extension

4 votes

Je suppose que cela dépend du contrat de la méthode (si elle s'attend à ce que .txt o txt ) mais comme ChangeExtension gère les deux cas, ça ne peut pas faire de mal

57voto

Maxence Points 5619
public static string GetTempFileName(string extension)
{
    string fileName;
    int attempt = 0;
    bool exit = false;
    do
    {
        fileName = Path.GetRandomFileName();
        fileName = Path.ChangeExtension(fileName, extension);
        fileName = Path.Combine(Path.GetTempPath(), fileName);

        try
        {
            using (new FileStream(fileName, FileMode.CreateNew)) {}

            exit = true;
        }
        catch (IOException ex)
        {
            if (++attempt == 10) 
                throw new IOException("No unique temporary file name is available.", ex);
        }

    } while (!exit);

    return fileName;
}

Remarque : cela fonctionne comme Path.GetTempFileName. Un fichier vide est créé pour réserver le nom du fichier. Elle fait 10 tentatives, en cas de collisions générées par Path.GetRandomFileName() ;

0 votes

Gardez à l'esprit que Path.GetRandomFileName() crée en fait un fichier de zéro octet sur le disque et renvoie le chemin complet de ce fichier. Vous n'utilisez pas ce fichier, seulement son nom pour changer l'extension. Donc, si vous ne vous assurez pas que vous supprimez ces fichiers temporaires, après 65535 appels à cette fonction, elle commencera à échouer.

11 votes

Vous avez mélangé GetTempFileName() y GetRandomFileName() . GetTempFileName() créer un fichier de zéro octet comme ma méthode, mais GetRandomFileName() ne crée pas de fichier. Extrait de la documentation : > Contrairement à GetTempFileName, GetRandomFileName ne crée pas de fichier. Votre lien pointe vers la mauvaise page.

19voto

Mehmet Aras Points 3901

Vous pouvez aussi utiliser alternativement System.CodeDom.Compiler.TempFileCollection .

string tempDirectory = @"c:\\temp";
TempFileCollection coll = new TempFileCollection(tempDirectory, true);
string filename = coll.AddExtension("txt", true);
File.WriteAllText(Path.Combine(tempDirectory,filename),"Hello World");

Ici, j'ai utilisé une extension txt mais vous pouvez spécifier ce que vous voulez. J'ai également mis l'indicateur keep à true pour que le fichier temporaire soit conservé après utilisation. Malheureusement, TempFileCollection crée un seul fichier aléatoire par extension. Si vous avez besoin de plus de fichiers temporaires, vous pouvez créer plusieurs instances de TempFileCollection.

10voto

Matías Points 3008

Pourquoi ne pas vérifier si le fichier existe ?

string fileName;
do
{
    fileName = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".csv";
} while (System.IO.File.Exists(fileName));

12 votes

File.Exist vous donne des informations sur le passé et n'est donc pas fiable. Entre le retour de File.Exist et l'exécution de votre code, il est possible que le fichier soit créé.

4 votes

... alors vous êtes en sécurité avec votre propre programme, mais pas avec un autre processus qui écrit un fichier sur cette même destination...

0 votes

@JaredPar et quelle est la probabilité que cela se produise ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X