Comment générer des noms de fichiers uniques en C #


131

J'ai implémenté un algorithme qui générera des noms uniques pour les fichiers qui seront sauvegardés sur le disque dur. J'ajoute DateTime: heures, minutes, secondes et millisecondes, mais cela génère toujours le nom en double des fichiers parce que je télécharge plusieurs fichiers à la fois.

Quelle est la meilleure solution pour générer des noms uniques pour les fichiers à stocker sur le disque dur afin qu'aucun fichier ne soit identique?


Cela dépend d'autres exigences; cette [ancienne] question était / est trop vague.
user2864740

Réponses:


240

Si la lisibilité n'a pas d'importance, utilisez les GUID .

Par exemple:

var myUniqueFileName = string.Format(@"{0}.txt", Guid.NewGuid());

ou plus court :

var myUniqueFileName = $@"{Guid.NewGuid()}.txt";

Dans mes programmes, j'essaye parfois par exemple 10 fois de générer un nom lisible ("Image1.png"… "Image10.png") et si cela échoue (car le fichier existe déjà), je retombe sur les GUID.

Mettre à jour:

Récemment, j'ai également utilisé à la DateTime.Now.Ticksplace des GUID:

var myUniqueFileName = string.Format(@"{0}.txt", DateTime.Now.Ticks);

ou

var myUniqueFileName = $@"{DateTime.Now.Ticks}.txt";

L'avantage pour moi est que cela génère un nom de fichier plus court et "plus joli", par rapport aux GUID.

Veuillez noter que dans certains cas (par exemple, lors de la génération d'un grand nombre de noms aléatoires en très peu de temps), cela peut créer des valeurs non uniques.

Tenez-vous-en aux GUID si vous voulez vraiment vous assurer que les noms de fichiers sont uniques, même lorsque vous les transférez vers d'autres ordinateurs.


7
J'aime utiliser Ticks comme GUID, c'est vraiment moche. Vous pouvez également obtenir un hachage des ticks qui réduit la longueur des caractères du nom de fichier. DateTime.Now.Ticks.GetHashCode().ToString("x").ToUpper()
WillMcKill

4
«Ticks» est prévisible et non thread-safe (car les mêmes «ticks» peuvent être obtenus à partir de plusieurs threads / processus). Cela ne convient pas à la génération de nom de fichier temporaire. La génération de X..1..N peut convenir aux tâches destinées à l'utilisateur (par exemple, la copie dans l'Explorateur), mais est douteuse pour le travail sur le serveur.
user2864740

90

Utilisation

Path.GetTempFileName()

ou utilisez le nouveau GUID ().

Path.GetTempFilename () sur MSDN .


Voici le lien vers le document MSDN: msdn.microsoft.com/en-us/library
...

3
Notez cependant que cela GetTempFileName()peut générer une exception si vous créez de nombreux fichiers de ce type sans les supprimer.
Joey le

21
"La méthode GetTempFileName lèvera une IOException si elle est utilisée pour créer plus de 65535 fichiers sans supprimer les fichiers temporaires précédents." dit l'article MSDN.
Çağdaş Tekin

1
ATTENTION: GetTempFileNameva créer un fichier. Cela signifie également qu'il choisit l'emplacement du chemin temporaire . D'autre part, GetRandomFileNameconvient pour générer un nom de fichier 8.3 qui peut être utilisé avec un chemin différent. (J'ai vu un code horrible qui utilise GetTempFileName avec un File.Delete juste pour utiliser le nom de fichier ailleurs ..)
user2864740

77
System.IO.Path.GetRandomFileName()

Path.GetRandomFileName () sur MSDN .


Voici le lien vers le document MSDN: msdn.microsoft.com/en-us/library
...

13
@RyBolt: Puisque vous n'êtes pas obligé de vous semer vous-même, il n'y a pratiquement rien à garder à l'esprit pour utiliser cette méthode. Et je m'attendrais à ce que la grande majorité des développeurs n'aient aucune idée de la façon de créer des systèmes cryptographiques sécurisés.
Joey

54

Si la lisibilité du nom de fichier n'est pas importante, le GUID, comme suggéré par beaucoup, fera l'affaire. Cependant, je trouve que la recherche dans un répertoire avec 1000 noms de fichiers GUID est très difficile à trier. J'utilise donc généralement une combinaison d'une chaîne statique qui donne au nom du fichier des informations de contexte, un horodatage et un GUID.

Par exemple:

public string GenerateFileName(string context)
{
    return context + "_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + "_" + Guid.NewGuid().ToString("N");
}

filename1 = GenerateFileName("MeasurementData");
filename2 = GenerateFileName("Image");

De cette façon, lorsque je trie par nom de fichier, il regroupera automatiquement les fichiers par chaîne de contexte et triera par horodatage.

Notez que la limite de nom de fichier dans Windows est de 255 caractères.


1
+1 Pour la suggestion d'inclure des informations utiles associées à un GUID. - Un aparté à prendre avec un grain de sel: inclure la date et l'heure dans un nom de fichier est un peu redondant quand vous le pouvez Right Click > Sort By > Date.
Timothy Shields

1
L'heure devient utile si vous stockez un tas de fichiers avec des contextes différents dans le même répertoire. Bien entendu, la génération du nom de fichier doit être ajustée en fonction de vos besoins spécifiques.
Mas

Devrait être Guid.NewGuid().ToString();. Parenthèse manquante. +1 sinon
Laurent W.

C'est très élégant. Horodatage et Guid. +1
JoshYates1980

J'aime cette solution +1, j'ai ajouté une deuxième extension de chaîne de paramètres que j'ajoute au fileName, cela soutient davantage l'idée de contexte et permet d'ouvrir facilement le fichier avec l'application par défaut en double-cliquant si nécessaire
shelbypereira

23

Voici un algorithme qui renvoie un nom de fichier lisible unique basé sur l'original fourni. Si le fichier d'origine existe, il essaie de manière incrémentielle d'ajouter un index au nom de fichier jusqu'à ce qu'il en trouve un qui n'existe pas. Il lit les noms de fichiers existants dans un HashSet pour vérifier les collisions, donc c'est assez rapide (quelques centaines de noms de fichiers par seconde sur ma machine), il est également sûr pour les threads et ne souffre pas des conditions de concurrence.

Par exemple, si vous le transmettez test.txt, il tentera de créer des fichiers dans cet ordre:

test.txt
test (2).txt
test (3).txt

etc. Vous pouvez spécifier le nombre maximum de tentatives ou simplement le laisser par défaut.

Voici un exemple complet:

class Program
{
    static FileStream CreateFileWithUniqueName(string folder, string fileName, 
        int maxAttempts = 1024)
    {
        // get filename base and extension
        var fileBase = Path.GetFileNameWithoutExtension(fileName);
        var ext = Path.GetExtension(fileName);
        // build hash set of filenames for performance
        var files = new HashSet<string>(Directory.GetFiles(folder));

        for (var index = 0; index < maxAttempts; index++)
        {
            // first try with the original filename, else try incrementally adding an index
            var name = (index == 0)
                ? fileName
                : String.Format("{0} ({1}){2}", fileBase, index, ext);

            // check if exists
            var fullPath = Path.Combine(folder, name);
            if(files.Contains(fullPath))
                continue;

            // try to create the file
            try
            {
                return new FileStream(fullPath, FileMode.CreateNew, FileAccess.Write);
            }
            catch (DirectoryNotFoundException) { throw; }
            catch (DriveNotFoundException) { throw; }
            catch (IOException) 
            {
                // Will occur if another thread created a file with this 
                // name since we created the HashSet. Ignore this and just
                // try with the next filename.
            } 
        }

        throw new Exception("Could not create unique filename in " + maxAttempts + " attempts");
    }

    static void Main(string[] args)
    {
        for (var i = 0; i < 500; i++)
        {
            using (var stream = CreateFileWithUniqueName(@"c:\temp\", "test.txt"))
            {
                Console.WriteLine("Created \"" + stream.Name + "\"");
            }
        }

        Console.ReadKey();
    }
}

thread-safe ? passtatic readonly variable non pluslock?
Kiquenet

La méthode elle-même est statique, donc ne partage rien, donc je crois que plusieurs threads peuvent entrer en toute sécurité dans cette méthode simultanément. Peut-être que thread-safe n'est pas tout à fait le terme correct - j'essaie de transmettre que si un autre thread / processus crée un fichier avec un nom en conflit lors de l'exécution, cette méthode récupère et essaie le prochain nom disponible. N'hésitez pas à modifier si vous pensez qu'il peut être amélioré.
Mike Chamberlain

Peut-être que "ne pas souffrir d'une condition raciale" est une meilleure façon de le dire.
Mike Chamberlain

10

J'utilise GetRandomFileName :

La méthode GetRandomFileName renvoie une chaîne aléatoire forte d'un point de vue cryptographique qui peut être utilisée comme nom de dossier ou nom de fichier. Contrairement à GetTempFileName, GetRandomFileName ne crée pas de fichier. Lorsque la sécurité de votre système de fichiers est primordiale, cette méthode doit être utilisée à la place de GetTempFileName.

Exemple:

public static string GenerateFileName(string extension="")
{
    return string.Concat(Path.GetRandomFileName().Replace(".", ""),
        (!string.IsNullOrEmpty(extension)) ? (extension.StartsWith(".") ? extension : string.Concat(".", extension)) : "");
}

La méthode GetRandomFileName () génère-t-elle toujours le nom de fichier unique à chaque fois similaire à GUID ()?
Ashish Shukla

1
@AshishShukla en fait, je n'ai aucune idée. msdn indique qu'une "chaîne aléatoire et cryptographiquement forte" est générée. Je n'ai eu aucun problème jusqu'à présent. Si l'unicité est essentielle, une vérification supplémentaire pourrait être une bonne idée.
Koray

3
  1. Créez votre nom de fichier horodaté en suivant votre processus normal
  2. Vérifiez si le nom de fichier existe
  3. Faux - enregistrer le fichier
  4. Vrai - Ajouter un caractère supplémentaire au fichier, peut-être un compteur
  5. Passez à l'étape 2

10
Cet algorithme est accessible à la concurrence
Jader Dias

3

Vous pouvez avoir un nom de fichier unique généré automatiquement pour vous sans aucune méthode personnalisée. Utilisez simplement ce qui suit avec la classe StorageFolder ou la classe StorageFile . La clé ici est: CreationCollisionOption.GenerateUniqueNameetNameCollisionOption.GenerateUniqueName

Pour créer un nouveau fichier avec un nom de fichier unique:

var myFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("myfile.txt", NameCollisionOption.GenerateUniqueName);

Pour copier un fichier vers un emplacement avec un nom de fichier unique:

var myFile2 = await myFile1.CopyAsync(ApplicationData.Current.LocalFolder, myFile1.Name, NameCollisionOption.GenerateUniqueName);

Pour déplacer un fichier avec un nom de fichier unique dans l'emplacement de destination:

await myFile.MoveAsync(ApplicationData.Current.LocalFolder, myFile.Name, NameCollisionOption.GenerateUniqueName);

Pour renommer un fichier avec un nom de fichier unique à l'emplacement de destination:

await myFile.RenameAsync(myFile.Name, NameCollisionOption.GenerateUniqueName);

2

J'ai utilisé le code suivant et cela fonctionne très bien. J'espère que cela pourrait vous aider.

Je commence par un nom de fichier unique en utilisant un horodatage -

"context_" + DateHeure.Now.ToString ("aaaaMMjjHHmmssffff")

Code C # -

public static string CreateUniqueFile(string logFilePath, string logFileName, string fileExt)
    {
        try
        {
            int fileNumber = 1;

            //prefix with . if not already provided
            fileExt = (!fileExt.StartsWith(".")) ? "." + fileExt : fileExt;

            //Generate new name
            while (File.Exists(Path.Combine(logFilePath, logFileName + "-" + fileNumber.ToString() + fileExt)))
                fileNumber++;

            //Create empty file, retry until one is created
            while (!CreateNewLogfile(logFilePath, logFileName + "-" + fileNumber.ToString() + fileExt))
                fileNumber++;

            return logFileName + "-" + fileNumber.ToString() + fileExt;
        }
        catch (Exception)
        {
            throw;
        }
    }

    private static bool CreateNewLogfile(string logFilePath, string logFile)
    {
        try
        {
            FileStream fs = new FileStream(Path.Combine(logFilePath, logFile), FileMode.CreateNew);
            fs.Close();
            return true;
        }
        catch (IOException)   //File exists, can not create new
        {
            return false;
        }
        catch (Exception)     //Exception occured
        {
            throw;
        }
    }

1

Avez-vous besoin de l'horodatage dans le nom de fichier?

Vous pouvez faire du nom de fichier un GUID.


@downvoter Une raison pour le vote défavorable? Un GUID pour un nom de fichier semble être une réponse populaire à cette question.
Larry Hipp

C'est une réponse répétée, et je n'ai pas assez de réputation pour voter contre
Jader Dias

@XMLforDummies ma réponse a été l'une des premières. Cela peut ne pas sembler comme ça maintenant parce que cela ne montre que les heures maintenant. C'est une réponse répétée car c'est probablement la bonne réponse.
Larry Hipp


1

Que diriez-vous d'utiliser Guid.NewGuid()pour créer un GUID et l'utiliser comme nom de fichier (ou une partie du nom de fichier avec votre horodatage si vous le souhaitez).


1

J'ai écrit une simple fonction récursive qui génère des noms de fichiers comme le fait Windows, en ajoutant un numéro de séquence avant l'extension de fichier.

Étant donné le chemin de fichier souhaité de C:\MyDir\MyFile.txt, et le fichier existe déjà, il renvoie un chemin de fichier final de C:\MyDir\MyFile_1.txt.

Il s'appelle ainsi:

var desiredPath = @"C:\MyDir\MyFile.txt";
var finalPath = UniqueFileName(desiredPath);

private static string UniqueFileName(string path, int count = 0)
{
    if (count == 0)
    {
        if (!File.Exists(path))
        {
            return path;
        }
    }
    else
    {
        var candidatePath = string.Format(
            @"{0}\{1}_{2}{3}",
            Path.GetDirectoryName(path),
            Path.GetFileNameWithoutExtension(path),
            count,
            Path.GetExtension(path));

        if (!File.Exists(candidatePath))
        {
            return candidatePath;
        }
    }

    count++;
    return UniqueFileName(path, count);
}

Ce n'est ni thread-safe ni process-safe. Il existe une condition de concurrence avec le contrôle File.Exists et toute création (supposée plus tard) du fichier. Trivialement, lorsqu'il est appelé deux fois de suite sans créer de fichier, il renvoie le même résultat.
user2864740

1

Pourquoi ne pouvons-nous pas créer un identifiant unique comme ci-dessous.

Nous pouvons utiliser DateTime.Now.Ticks et Guid.NewGuid (). ToString () pour combiner ensemble et créer un identifiant unique.

Lorsque le DateTime.Now.Ticks est ajouté, nous pouvons connaître la date et l'heure en secondes auxquelles l'identifiant unique est créé.

Veuillez consulter le code.

var ticks = DateTime.Now.Ticks;
var guid = Guid.NewGuid().ToString();
var uniqueSessionId = ticks.ToString() +'-'+ guid; //guid created by combining ticks and guid

var datetime = new DateTime(ticks);//for checking purpose
var datetimenow = DateTime.Now;    //both these date times are different.

Nous pouvons même prendre la part des ticks dans l'identifiant unique et vérifier la date et l'heure plus tard pour référence future.

Vous pouvez joindre l'identifiant unique créé au nom de fichier ou peut être utilisé pour créer un identifiant de session unique pour la connexion-déconnexion des utilisateurs à notre application ou site Web.


Pourquoi s'embêter avec des «ticks» s'il y a un GUID?
user2864740

Dans n'importe quel scénario, si vous devez vérifier quand l'uniqueSessionId est généré, vous obtiendrez l'heure exacte. Et aussi à cette tique spécifique ne se produira qu'une seule fois dans la vie.
Jineesh Uvantavida

Trivialement, cette hypothèse sur les ticks est invalide: 1) plusieurs observateurs peuvent voir le même 'tick' (pensez threads / processus) et 2) le même 'tick' peut être observé plusieurs fois par le même observateur, s'il est interrogé assez rapidement.
user2864740

Cependant, en utilisant simplement Guid.NewGuid (et en ignorant ce fait qu'il n'est pas "cryptographiquement aléatoire" qui pourrait être intéressant dans certains cas), nous pouvons affirmer qu'avec une probabilité suffisamment élevée que nous ne nous soucions pas du contraire, un identifiant unique sera être généré - c'est une garantie beaucoup, beaucoup plus élevée que les «ticks» . Ainsi, les 'ticks' n'ont aucune valeur / utilisation attendue ici en tant que données "secondaires" poussées dans le nom de fichier.
user2864740

(FWIW: Je viens de corriger du code avec une assertion cassée sur le 'temps unique' ..)
user2864740

0

Si vous souhaitez avoir la date / heure, les heures, les minutes, etc., vous pouvez utiliser une variable statique. Ajoutez la valeur de cette variable au nom de fichier. Vous pouvez démarrer le compteur avec 0 et l'incrémenter lorsque vous avez créé un fichier. De cette façon, le nom de fichier sera sûrement unique puisque vous avez également des secondes dans le fichier.


0

Je fais généralement quelque chose de ce genre:

  • commencez par un nom de fichier racine ( work.dat1par exemple)
  • essayez de le créer avec CreateNew
  • si cela fonctionne, vous avez le fichier, sinon ...
  • mélanger la date / heure actuelle dans le nom de fichier ( work.2011-01-15T112357.datpar exemple)
  • essayez de créer le fichier
  • si cela a fonctionné, vous avez le fichier, sinon ...
  • Mélangez un compteur monotone dans le nom du fichier ( work.2011-01-15T112357.0001.datpar exemple (je n'aime pas les GUID. Je préfère l'ordre / la prévisibilité).
  • essayez de créer le fichier. Continuez à cocher le compteur et réessayez jusqu'à ce qu'un fichier soit créé pour vous.

Voici un exemple de classe:

static class DirectoryInfoHelpers
{
    public static FileStream CreateFileWithUniqueName( this DirectoryInfo dir , string rootName )
    {
        FileStream fs = dir.TryCreateFile( rootName ) ; // try the simple name first

        // if that didn't work, try mixing in the date/time
        if ( fs == null )
        {
            string date = DateTime.Now.ToString( "yyyy-MM-ddTHHmmss" ) ;
            string stem = Path.GetFileNameWithoutExtension(rootName) ;
            string ext  = Path.GetExtension(rootName) ?? ".dat" ;

            ext = ext.Substring(1);

            string fn = string.Format( "{0}.{1}.{2}" , stem , date , ext ) ;
            fs = dir.TryCreateFile( fn ) ;

            // if mixing in the date/time didn't work, try a sequential search
            if ( fs == null )
            {
                int seq = 0 ;
                do
                {
                    fn = string.Format( "{0}.{1}.{2:0000}.{3}" , stem , date , ++seq , ext ) ;
                    fs = dir.TryCreateFile( fn ) ;
                } while ( fs == null ) ;
            }

        }

        return fs ;
    }

    private static FileStream TryCreateFile(this DirectoryInfo dir , string fileName )
    {
        FileStream fs = null ;
        try
        {
            string fqn = Path.Combine( dir.FullName , fileName ) ;

            fs = new FileStream( fqn , FileMode.CreateNew , FileAccess.ReadWrite , FileShare.None ) ;
        }
        catch ( Exception )
        {
            fs = null ;
        }
        return fs ;
    }

}

Vous voudrez peut-être modifier l'algorithme (utilisez toujours tous les composants possibles pour le nom de fichier par exemple). Dépend du contexte - Si je créais des fichiers journaux par exemple, que je pourrais vouloir faire disparaître, vous voudriez qu'ils partagent tous le même modèle avec le nom.

Le code n'est pas parfait (pas de contrôle sur les données transmises par exemple). Et l'algorithme n'est pas parfait (si vous remplissez le disque dur ou rencontrez des autorisations, des erreurs d'E / S réelles ou d'autres erreurs du système de fichiers, par exemple, cela se bloquera, en l'état, dans une boucle infinie).


0

Je finis par concaténer GUID avec la chaîne Jour Mois Année Deuxième Milliseconde et je pense que cette solution est assez bonne dans mon scénario



0

J'ai écrit une classe spécialement pour cela. Il est initialisé avec une partie «de base» (par défaut, un horodatage précis à la minute) et après cela ajoute des lettres pour créer des noms uniques. Ainsi, si le premier tampon généré est 1907101215a, le second sera 1907101215b, puis 1907101215c, et cetera.

Si j'ai besoin de plus de 25 timbres uniques, j'utilise des z unaires pour compter 25. Donc, ça va 1907101215y, 1907101215za, 1907101215zb, ... 1907101215zy, 1907101215zza, 1907101215zzb, et ainsi de suite. Cela garantit que les tampons seront toujours triés de manière alphanumérique dans l'ordre dans lequel ils ont été générés (tant que le caractère suivant après le tampon n'est pas une lettre).

Il n'est pas sûr pour les threads, ne met pas automatiquement à jour l'heure et gonfle rapidement si vous avez besoin de centaines de tampons, mais je le trouve suffisant pour mes besoins.

/// <summary>
/// Class for generating unique stamps (for filenames, etc.)
/// </summary>
/// <remarks>
/// Each time ToString() is called, a unique stamp is generated.
/// Stamps are guaranteed to sort alphanumerically in order of generation.
/// </remarks>
public class StampGenerator
{
  /// <summary>
  /// All the characters which could be the last character in the stamp.
  /// </summary>
  private static readonly char[] _trailingChars =
  {
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
    'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
    'u', 'v', 'w', 'x', 'y'
  };

  /// <summary>
  /// How many valid trailing characters there are.
  /// </summary>
  /// <remarks>Should always equal _trailingChars.Length</remarks>
  public const int TRAILING_RANGE = 25;

  /// <summary>
  /// Maximum length of the stamp. Hard-coded for laziness.
  /// </summary>
  public const int MAX_LENGTH_STAMP = 28;

  /// <summary>
  /// Base portion of the stamp. Will be constant between calls.
  /// </summary>
  /// <remarks>
  /// This is intended to uniquely distinguish between instances.
  /// Default behavior is to generate a minute-accurate timestamp.
  /// </remarks>
  public string StampBase { get; }

  /// <summary>
  /// Number of times this instance has been called.
  /// </summary>
  public int CalledTimes { get; private set; }

  /// <summary>
  /// Maximum number of stamps that can be generated with a given base.
  /// </summary>
  public int MaxCalls { get; }

  /// <summary>
  /// Number of stamps remaining for this instance.
  /// </summary>
  public int RemainingCalls { get { return MaxCalls - CalledTimes; } }

  /// <summary>
  /// Instantiate a StampGenerator with a specific base.
  /// </summary>
  /// <param name="stampBase">Base of stamp.</param>
  /// <param name="calledTimes">
  /// Number of times this base has already been used.
  /// </param>
  public StampGenerator(string stampBase, int calledTimes = 0)
  {
    if (stampBase == null)
    {
      throw new ArgumentNullException("stampBase");
    }
    else if (Regex.IsMatch(stampBase, "[^a-zA-Z_0-9 \\-]"))
    {
      throw new ArgumentException("Invalid characters in Stamp Base.",
                                  "stampBase");
    }
    else if (stampBase.Length >= MAX_LENGTH_STAMP - 1)
    {
      throw new ArgumentException(
        string.Format("Stamp Base too long. (Length {0} out of {1})",
                      stampBase.Length, MAX_LENGTH_STAMP - 1), "stampBase");
    }
    else if (calledTimes < 0)
    {
      throw new ArgumentOutOfRangeException(
        "calledTimes", calledTimes, "calledTimes cannot be negative.");
    }
    else
    {
      int maxCalls = TRAILING_RANGE * (MAX_LENGTH_STAMP - stampBase.Length);
      if (calledTimes >= maxCalls)
      {
        throw new ArgumentOutOfRangeException(
          "calledTimes", calledTimes, string.Format(
            "Called Times too large; max for stem of length {0} is {1}.",
            stampBase.Length, maxCalls));
      }
      else
      {
        StampBase = stampBase;
        CalledTimes = calledTimes;
        MaxCalls = maxCalls;
      }
    }
  }

  /// <summary>
  /// Instantiate a StampGenerator with default base string based on time.
  /// </summary>
  public StampGenerator() : this(DateTime.Now.ToString("yMMddHHmm")) { }

  /// <summary>
  /// Generate a unique stamp.
  /// </summary>
  /// <remarks>
  /// Stamp values are orered like this:
  /// a, b, ... x, y, za, zb, ... zx, zy, zza, zzb, ...
  /// </remarks>
  /// <returns>A unique stamp.</returns>
  public override string ToString()
  {
    int zCount = CalledTimes / TRAILING_RANGE;
    int trailing = CalledTimes % TRAILING_RANGE;
    int length = StampBase.Length + zCount + 1;

    if (length > MAX_LENGTH_STAMP)
    {
      throw new InvalidOperationException(
        "Stamp length overflown! Cannot generate new stamps.");
    }
    else
    {
      CalledTimes = CalledTimes + 1;
      var builder = new StringBuilder(StampBase, length);
      builder.Append('z', zCount);
      builder.Append(_trailingChars[trailing]);
      return builder.ToString();
    }
  }
}

-1

DateTime.Now.Ticksn'est pas sûr, Guid.NewGuid()est trop moche, si vous avez besoin de quelque chose de propre et presque sûr ( ce n'est pas sûr à 100% par exemple si vous l'appelez 1000000 fois en 1 ms ), essayez:

Math.Abs(Guid.NewGuid().GetHashCode())

Par sûr, je veux dire sûr d'être unique lorsque vous l'appelez autant de fois en très peu de temps.


Y a-t-il un problème avec ma solution downvoter? s'il vous plaît, faites-moi savoir.
Mehdi Dehghani

La GetHashCodeméthode renvoie an int, qui a une plage de 32 bits, tandis que GUIDa a une plage de 128 bits, et est donc beaucoup plus susceptible d'être unique. Si vous n'aimez pas le format d'une GUIDvaleur, appelez-la simplement ToString("N"), ce qui supprime les tirets.
4thex
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.