C # 'da benzersiz dosya adları nasıl oluşturulur


131

Sabit diske kaydedilecek dosyalar için benzersiz adlar oluşturacak bir algoritma uyguladım. Ekliyorum DateTime: Saat, Dakika, Saniye ve Milisaniye ama yine de bir seferde birden fazla dosya yüklediğim için yinelenen dosya adı oluşturuyor.

2 dosya aynı olmayacak şekilde sabit sürücüde depolanacak dosyalar için benzersiz adlar oluşturmanın en iyi çözümü nedir?


Diğer gereksinimlere bağlıdır; bu [eski] soru çok belirsizdi / belirsizdi.
user2864740

Yanıtlar:


240

Okunabilirlik önemli değilse, GUID'leri kullanın .

Örneğin:

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

veya daha kısa :

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

Programlarımda, bazen örneğin 10 kez okunabilir bir ad oluşturmayı deniyorum ("Image1.png"… "Image10.png") ve bu başarısız olursa (dosya zaten var olduğu için) GUID'lere geri dönüyorum.

Güncelleme:

Son zamanlarda DateTime.Now.TicksGUID'ler yerine de kullanıyorum :

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

veya

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

Bana faydası, bunun GUID'lere kıyasla daha kısa ve "daha güzel görünen" bir dosya adı oluşturmasıdır.

Bazı durumlarda bu (örneğin çok kısa sürede rastgele birçok isim oluştururken), bu unutmayınız kudretini benzersiz olmayan değerler olun.

Dosya adlarının diğer bilgisayarlara aktarılırken bile benzersiz olduğundan gerçekten emin olmak istiyorsanız GUID'lere bağlı kalın.


7
Ticks'i GUID olarak kullanmayı seviyorum gerçekten çirkin. Ayrıca, dosya adının karakter uzunluğunu azaltan Ticks'in bir karmasını da alabilirsiniz. DateTime.Now.Ticks.GetHashCode().ToString("x").ToUpper()
WillMcKill

4
"Keneler" tahmin edilebilirdir ve iş parçacığı için güvenli değildir (çünkü aynı "işaretler" birden çok iş parçacığından / işlemden elde edilebilir). Bu, geçici dosya adı oluşturma için uygun olmamasına neden olur. X..1..N'nin oluşturulması kullanıcıya yönelik görevler için uygun olabilir (yani, Explorer'da kopyalama), ancak sunucu çalışması için şüphelidir.
user2864740

90

kullanım

Path.GetTempFileName()

veya yeni GUID () kullanın.

MSDN'de Path.GetTempFilename () .


İşte MSDN
belgesinin

3
Yine de, GetTempFileName()silmeden bu tür birçok dosya oluşturursanız , bunun bir istisna oluşturabileceğini unutmayın.
Joey

21
"GetTempFileName yöntemi, önceki geçici dosyaları silmeden 65535'ten fazla dosya oluşturmak için kullanılırsa bir IOException oluşturur." MSDN makalesi diyor.
Çağdaş Tekin

1
UYARI: GetTempFileNameedecek oluşturmak Dosya. Bu aynı zamanda geçici yol konumunu seçtiği anlamına gelir . Öte yandan, farklı bir yolla kullanılabilen GetRandomFileNamebir 8.3 dosya adı oluşturmak için uygundur . (
GetTempFileName'i

77
System.IO.Path.GetRandomFileName()

MSDN'de Path.GetRandomFileName () .


İşte MSDN
belgesinin

13
@RyBolt: Kendinizi tohumlamanız gerekmediğinden, bu yöntemi kullanmak için aklınızda tutmanız gereken neredeyse hiçbir şey yok. Ve geliştiricilerin büyük çoğunluğunun güvenli kriptografik sistemlerin nasıl inşa edileceği konusunda hiçbir fikrinin olmamasını bekliyorum.
Joey

54

Dosya adının okunabilirliği önemli değilse, birçok kişinin önerdiği gibi GUID işe yarar. Bununla birlikte, 1000 GUID dosya adına sahip bir dizine bakmanın sıralanması çok zor olduğunu görüyorum. Bu yüzden genellikle dosya adına bazı bağlam bilgileri, bir zaman damgası ve GUID veren statik bir dizenin bir kombinasyonunu kullanırım.

Örneğin:

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

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

Bu şekilde, dosya adına göre sıraladığımda, dosyaları otomatik olarak bağlam dizesine göre gruplayacak ve zaman damgasına göre sıralayacaktır.

Windows'ta dosya adı sınırının 255 karakter olduğunu unutmayın.


1
+1 Önerinin bir GUID ile birleştirilmiş yararlı bilgileri içermesi için . - Biraz tuzlu olmak için bir kenara: bir dosya adına tarih ve saat eklemek, yapabildiğiniz zaman biraz gereksizdir Right Click > Sort By > Date.
Timothy Shields

1
Aynı dizinde farklı bağlamlara sahip bir grup dosyayı depoluyorsanız, zaman kullanışlı hale gelir. Elbette, dosya adı oluşturma özel ihtiyaçlarınıza göre ayarlanmalıdır.
Mas

Olmalı Guid.NewGuid().ToString();. Eksik parantez. Aksi takdirde +1
Laurent W.

Bu çok şık. Zaman Damgası ve Kılavuz. +1
JoshYates1980

Bu çözüm + 1'i beğendim, fileName'e eklediğim ikinci bir parametre dizesi uzantısı ekledim, bu bağlam fikrini daha da destekliyor ve gerekirse çift tıklama ile dosyayı varsayılan uygulama ile kolayca açmaya izin veriyor
shelbypereira

23

Burada, sağlanan orijinali temel alan benzersiz bir okunabilir dosya adı döndüren bir algoritma var. Orijinal dosya mevcutsa, varolmayan bir dosya bulana kadar dosya adına bir dizin eklemeye çalışır. Çarpışmaları kontrol etmek için mevcut dosya adlarını bir HashSet'e okur, böylece oldukça hızlıdır (makinemde saniyede birkaç yüz dosya adı), iş parçacığı da güvenlidir ve yarış koşullarından zarar görmez.

Örneğin, eğer bunu geçerseniz test.txt, dosyaları şu sırayla oluşturmaya çalışacaktır:

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

vb. Maksimum deneme sayısını belirleyebilir veya varsayılan olarak bırakabilirsiniz.

İşte eksiksiz bir örnek:

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();
    }
}

iş parçacığı güvenli mi? değilstatic readonly değişken nelock?
Kiquenet

Yöntemin kendisi statiktir, bu nedenle hiçbir şey paylaşmaz, bu yüzden birden çok iş parçacığının bu yöntemi aynı anda güvenle girebileceğine inanıyorum. Belki de iş parçacığı güvenli tam olarak doğru bir terim değildir - başka bir iş parçacığı / işlem yürütme sırasında çakışan bir ada sahip bir dosya oluşturursa, bu yöntemin bir sonraki kullanılabilir adı kurtaracağını ve denediğini ifade etmeye çalışıyorum. İyileştirilebileceğini düşünüyorsanız düzenlemekten çekinmeyin.
Mike Chamberlain

Belki de "bir yarış durumundan muzdarip olmamak" daha iyi bir ifade şeklidir.
Mike Chamberlain

10

Kullandığım GetRandomFileName :

GetRandomFileName yöntemi, bir klasör adı veya dosya adı olarak kullanılabilen şifreleme açısından güçlü, rastgele bir dize döndürür. GetTempFileName'den farklı olarak, GetRandomFileName bir dosya oluşturmaz. Dosya sisteminizin güvenliği çok önemli olduğunda, GetTempFileName yerine bu yöntem kullanılmalıdır.

Misal:

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

GetRandomFileName () yöntemi her zaman her seferinde GUID () 'ye benzer benzersiz dosya adı oluşturur mu?
Ashish Shukla

1
@AshishShukla aslında hiçbir fikrim yok. msdn "kriptografik olarak güçlü, rastgele bir dizge" oluşturulduğunu söylüyor. Şimdiye kadar hiç problem yaşamadım. Benzersizlik kritikse, fazladan bir kontrol iyi bir fikir olabilir.
Koray

3
  1. Normal sürecinizi izleyerek zaman damgalı dosya adınızı oluşturun
  2. Dosya adının var olup olmadığını kontrol edin
  3. Yanlış - dosyayı kaydet
  4. Doğru - Dosyaya ek karakter, belki bir sayaç ekleyin
  5. 2. adıma gidin

10
Bu algoritma eşzamanlılık için kazanılabilir
Jader Dias

3

Herhangi bir özel yöntem olmadan sizin için otomatik olarak oluşturulan benzersiz bir dosya adına sahip olabilirsiniz. StorageFolder Class veya StorageFile Class ile aşağıdakileri kullanmanız yeterlidir . Buradaki anahtar şudur: CreationCollisionOption.GenerateUniqueNameveNameCollisionOption.GenerateUniqueName

To oluşturmak benzersiz dosya adıyla yeni bir dosya:

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

To kopyalamak benzersiz dosya adına sahip bir konuma bir dosya:

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

To hareket hedef konumda eşsiz bir dosya adıyla bir dosya:

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

To adlandırmak hedef konumda eşsiz bir dosya adıyla bir dosya:

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

2

Aşağıdaki kodu kullanıyorum ve iyi çalışıyor. Umarım bu size yardımcı olabilir.

Bir zaman damgası kullanarak benzersiz bir dosya adıyla başlıyorum -

"bağlam_" + DateTime.Now.ToString ("yyyyMMddHHmmssffff")

C # kodu -

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

Dosya adında tarih ve saat damgasına ihtiyacınız var mı?

Dosya adını bir GUID yapabilirsiniz.


@downvoter Olumsuz oylama için herhangi bir neden var mı? Dosya adı için bir GUID, bu soruya popüler bir cevap gibi görünüyor.
Larry Hipp

Tekrarlanan bir cevap ve olumsuz oy verecek kadar itibarım yok
Jader Dias

@XMLforDummies cevabım ilklerden biriydi. Şu anki gibi görünmeyebilir çünkü şimdiye kadar sadece saatleri gösteriyor. Tekrarlanan bir cevap çünkü muhtemelen doğru cevap bu.
Larry Hipp


1

Kullanarak Guid.NewGuid()bir GUID oluşturmaya ve bunu dosya adı olarak kullanmaya ne dersiniz (veya isterseniz dosya adının bir parçasıyla birlikte zaman damganızla birlikte).


1

Dosya uzantısının önüne bir sıra numarası ekleyerek Windows gibi dosya adları oluşturan basit bir özyinelemeli işlev yazdım.

İçin istenen bir dosya yolu verildiğinde C:\MyDir\MyFile.txtve dosya zaten mevcutsa, son bir dosya yolu döndürür C:\MyDir\MyFile_1.txt.

Şöyle denir:

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);
}

Bu, iş parçacığı veya işlem açısından güvenli değildir. File.Exists denetimi ve dosyanın herhangi bir (daha sonra olduğu varsayılan) oluşturulmasıyla bir yarış koşulu vardır. Önemsiz bir şekilde, bir dosya oluşturmadan art arda iki kez çağrıldığında aynı sonucu döndürür.
user2864740

1

Neden aşağıdaki gibi benzersiz bir kimlik yapamıyoruz?

DateTime.Now.Ticks ve Guid.NewGuid (). ToString () 'i bir araya getirmek ve benzersiz bir kimlik oluşturmak için kullanabiliriz.

DateTime.Now.Ticks eklendikçe, benzersiz id'nin oluşturulduğu saniye cinsinden Tarih ve Saati bulabiliriz.

Lütfen koda bakın.

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.

Eşsiz kimlikteki kenelerin bir kısmını bile alabilir ve ileride başvurmak için daha sonra tarih ve saati kontrol edebiliriz.

Oluşturulan benzersiz kimliği dosya adına ekleyebilir veya kullanıcıların uygulamamıza veya web sitemize giriş-çıkışları için benzersiz oturum kimliği oluşturmak için kullanılabilir.


Bir GUID varsa neden 'işaretler' ile uğraşasınız ki?
user2864740

Herhangi bir senaryo sırasında, uniqueSessionId'nin ne zaman oluşturulduğunu kontrol etmeniz gerekirse, tam zamanı alırsınız. Ve ayrıca bu belirli kene, ömür boyu yalnızca bir kez meydana gelecektir.
Jineesh Uvantavida

Önemsiz bir şekilde, keneler hakkındaki bu varsayım geçersizdir: 1) birden fazla gözlemci aynı 'tik'i' görebilir (konuları / süreçleri düşünebilir) ve 2) aynı 'tik', yeterince hızlı sorgulanırsa, aynı gözlemci tarafından birden çok kez gözlemlenebilir.
user2864740

Ancak, tarafından sadece kullanılarak Guid.NewGuid (ve bazı durumlarda ilginizi çekebilecek hangi "şifreli rasgele" olmadığı gerçeği göz ardı), biz, yaklaşık aksi benzersiz bir kimlik olacaktır umurumda değil yeterince yüksek olasılıkla, iddia edebilir üretilebilir - bu, 'kenelerden' çok, çok daha yüksek bir garantidir . Bu nedenle, 'işaretlerin' hiçbir değeri / kullanımı yoktur, burada dosya adına eklenen "ikincil" veriler olarak beklenir.
user2864740

(FWIW: Bazı kodu 'benzersiz zaman' ile ilgili yukarıda belirtilen bozuk bir iddiayla
düzelttim

0

Tarih saat, saat, dakika vb. Sahip olmak istiyorsanız statik değişken kullanabilirsiniz. Bu değişkenin değerini dosya adına ekleyin. Sayacı 0 ile başlatabilir ve bir dosya oluşturduğunuzda artırabilirsiniz. Bu şekilde dosya adı kesinlikle benzersiz olacaktır, çünkü dosyada da saniyeleriniz vardır.


0

Genelde şu satırlar boyunca bir şeyler yaparım:

  • bir kök dosya adıyla başlayın ( work.dat1örneğin)
  • CreateNew ile oluşturmayı deneyin
  • eğer işe yararsa, dosya sende, yoksa ...
  • mevcut tarih / saati dosya adına karıştırın ( work.2011-01-15T112357.datörneğin)
  • dosyayı oluşturmayı dene
  • eğer işe yaradıysa, dosyayı aldın, yoksa ...
  • Dosya adına bir monoton sayacı karıştırın (work.2011-01-15T112357.0001.dat örneğin. (GUID'leri sevmiyorum. Sırayı / tahmin edilebilirliği tercih ederim.)
  • dosyayı oluşturmayı deneyin. Sayacı çalıştırmaya ve sizin için bir dosya oluşturulana kadar yeniden denemeye devam edin.

İşte örnek bir sınıf:

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

}

Algoritmayı değiştirmek isteyebilirsiniz (örneğin, her zaman olası tüm bileşenleri dosya adına kullanın). Bağlama bağlıdır - Örneğin, varolmadan döndürmek isteyebileceğim günlük dosyaları oluşturuyor olsaydım, hepsinin aynı kalıbı adla paylaşmasını istersiniz.

Kod mükemmel değil (örneğin, aktarılan veriler üzerinde kontrol yok). Ve algoritma mükemmel değildir (eğer sabit diski doldurursanız veya izinlerle, gerçek G / Ç hatalarıyla veya diğer dosya sistemi hatalarıyla karşılaşırsanız, örneğin, bu durduğu haliyle sonsuz bir döngüde asılı kalacaktır).


0

GUID'i Gün Ay Yıl İkinci Milisaniye dizesiyle bitirdim ve bu çözümün senaryomda oldukça iyi olduğunu düşünüyorum



0

Bunu yapmak için özel olarak bir ders yazdım. Bir "temel" bölüm ile başlatılır (varsayılan olarak dakika-doğru zaman damgasıdır) ve bundan sonra benzersiz isimler yapmak için harfleri ekler. Dolayısıyla, üretilen ilk damga 1907101215a ise, ikincisi 1907101215b, ardından 1907101215c vb. Olur.

25'ten fazla benzersiz damgaya ihtiyacım olursa, 25'leri saymak için tekli 'z'leri kullanırım. Yani, 1907101215y, 1907101215za, 1907101215zb, ... 1907101215zy, 1907101215zza, 1907101215zzb vb. Bu, pulların her zaman üretildikleri sırayla alfanümerik olarak sıralanmasını garanti eder (damgalardan sonraki karakter bir harf olmadığı sürece).

İş parçacığı açısından güvenli değil, saati otomatik olarak güncellemez ve yüzlerce damgaya ihtiyacınız varsa hızla şişer, ancak ben bunu ihtiyaçlarım için yeterli buluyorum.

/// <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.Ticksgüvenli değil Guid.NewGuid(), çok çirkin, temiz ve neredeyse güvenli bir şeye ihtiyacınız varsa ( % 100 güvenli değildir, örneğin 1 ms'de 1.000.000 kez ararsanız ), şunu deneyin:

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

Güvenli derken, çok kısa bir süre içinde birkaç kez aradığınızda benzersiz olmayı kastediyorum .


Çözüm düşürücümle ilgili herhangi bir sorun var mı? Lütfen bana haber ver.
Mehdi Dehghani

GetHashCodeYöntem, döner intbir oysa 32 bit aralığı olan, GUIDbir 128-bit aralığına sahiptir ve bu yüzden daha büyük olasılıkla benzersiz olmaktır. Bir GUIDdeğerin biçimini beğenmezseniz ToString("N"), çizgileri kaldıran onu çağırmanız yeterlidir .
4.ex
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.