답변:
가독성이 중요하지 않으면 GUID를 사용하십시오 .
예 :
var myUniqueFileName = string.Format(@"{0}.txt", Guid.NewGuid());
또는 더 짧은 :
var myUniqueFileName = $@"{Guid.NewGuid()}.txt";
내 프로그램에서 읽을 수있는 이름 ( "Image1.png"… "Image10.png")을 생성하기 위해 예를 들어 10 번 시도하는 경우가 있는데 (파일이 이미 있기 때문에) 실패하면 GUID로 돌아갑니다.
최신 정보:
최근 DateTime.Now.Ticks에는 GUID 대신 사용 했습니다.
var myUniqueFileName = string.Format(@"{0}.txt", DateTime.Now.Ticks);
또는
var myUniqueFileName = $@"{DateTime.Now.Ticks}.txt";
나에게 이점은 이것이 GUID에 비해 더 짧고 "더욱보기 좋은"파일 이름을 생성한다는 것입니다.
경우에 따라 (예 : 매우 짧은 시간에 많은 임의의 이름을 생성 할 때) 고유하지 않은 값을 만들 수 있습니다 .
다른 컴퓨터로 파일을 전송할 때에도 파일 이름이 고유한지 확인하려면 GUID를 고수하십시오.
DateTime.Now.Ticks.GetHashCode().ToString("x").ToUpper()
GetTempFileName()그러한 파일을 삭제하지 않고 많은 파일을 작성하면 예외가 발생할 수 있습니다.
GetTempFileName을 생성 합니다. 또한 임시 경로 위치를 선택합니다 . 반면에 다른 경로와 함께 사용할 수 GetRandomFileName있는 8.3 파일 이름 을 생성하는 데 적합 합니다. (다른 곳에 파일 이름을 사용하기 위해 File.Delete와 함께 GetTempFileName을 사용하는 일부 무시한 코드를 보았습니다.)
System.IO.Path.GetRandomFileName()
파일 이름의 가독성이 중요하지 않은 경우 많은 사람들이 제안한 GUID가 중요합니다. 그러나 1000 개의 GUID 파일 이름을 가진 디렉토리를 살펴보면 분류하기가 매우 어렵다는 것을 알았습니다. 따라서 일반적으로 파일 이름에 컨텍스트 정보, 타임 스탬프 및 GUID를 제공하는 정적 문자열의 조합을 사용합니다.
예를 들면 다음과 같습니다.
public string GenerateFileName(string context)
{
return context + "_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + "_" + Guid.NewGuid().ToString("N");
}
filename1 = GenerateFileName("MeasurementData");
filename2 = GenerateFileName("Image");
이렇게하면 파일 이름으로 정렬하면 컨텍스트 문자열로 파일을 자동으로 그룹화하고 타임 스탬프로 정렬합니다.
창의 파일 이름 제한은 255 자입니다.
Right Click > Sort By > Date.
Guid.NewGuid().ToString();합니다. 괄호가 없습니다. +1
다음은 제공된 원본을 기준으로 읽을 수있는 고유 한 파일 이름을 반환하는 알고리즘입니다. 원본 파일이 있으면 존재하지 않는 파일을 찾을 때까지 파일 이름에 색인을 추가하려고합니다. 충돌을 확인하기 위해 기존 파일 이름을 HashSet으로 읽어들이므로 매우 빠르며 (내 컴퓨터에서 초당 수백 개의 파일 이름) 스레드 안전하고 경쟁 조건으로 고통받지 않습니다.
예를 들어, 전달하면 test.txt다음 순서로 파일을 작성하려고 시도합니다.
test.txt
test (2).txt
test (3).txt
최대 시도 횟수를 지정하거나 기본값을 그대로 두십시오.
다음은 완전한 예입니다.
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();
}
}
static readonly 변수 도lock?
GetRandomFileName을 사용합니다 .
GetRandomFileName 메서드는 폴더 이름 또는 파일 이름으로 사용할 수있는 암호로 강력한 임의 문자열을 반환합니다. GetTempFileName과 달리 GetRandomFileName은 파일을 만들지 않습니다. 파일 시스템의 보안이 가장 중요한 경우 GetTempFileName 대신이 방법을 사용해야합니다.
예:
public static string GenerateFileName(string extension="")
{
return string.Concat(Path.GetRandomFileName().Replace(".", ""),
(!string.IsNullOrEmpty(extension)) ? (extension.StartsWith(".") ? extension : string.Concat(".", extension)) : "");
}
사용자 정의 방법없이 고유 한 파일 이름이 자동으로 생성되도록 할 수 있습니다. 다만 다음과 같은 사용 StorageFolder 클래스 또는 StorageFile 클래스 . 여기서 핵심은 다음 CreationCollisionOption.GenerateUniqueName과NameCollisionOption.GenerateUniqueName
고유 한 파일 이름으로 새 파일 을 만들려면
var myFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("myfile.txt", NameCollisionOption.GenerateUniqueName);
파일 이름이 고유 한 위치에 파일 을 복사 하려면
var myFile2 = await myFile1.CopyAsync(ApplicationData.Current.LocalFolder, myFile1.Name, NameCollisionOption.GenerateUniqueName);
대상 위치에서 고유 한 파일 이름을 가진 파일 을 이동 하려면
await myFile.MoveAsync(ApplicationData.Current.LocalFolder, myFile.Name, NameCollisionOption.GenerateUniqueName);
대상 위치에서 고유 한 파일 이름 으로 파일 이름 을 바꾸려면
await myFile.RenameAsync(myFile.Name, NameCollisionOption.GenerateUniqueName);
다음 코드를 사용하고 정상적으로 작동합니다. 이것이 도움이되기를 바랍니다.
타임 스탬프를 사용하여 고유 한 파일 이름으로 시작합니다.
"context_"+ DateTime.Now.ToString ( "yyyyMMddHHmmssffff")
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;
}
}
파일 이름에 날짜 시간 소인이 필요합니까?
파일 이름을 GUID로 만들 수 있습니다.
Guid.NewGuid()GUID를 만들고 파일 이름으로 사용하거나 파일 이름의 일부로 타임 스탬프와 함께 사용하는 방법은 어떻습니까 ?
파일 확장명 앞에 시퀀스 번호를 추가하여 Windows와 같은 파일 이름을 생성하는 간단한 재귀 함수를 작성했습니다.
원하는 파일 경로가 C:\MyDir\MyFile.txt있고 파일이 이미 존재하면 최종 파일 경로는을 (를) 반환합니다 C:\MyDir\MyFile_1.txt.
다음과 같이 호출됩니다.
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);
}
아래와 같이 고유 ID를 만들 수없는 이유는 무엇입니까?
DateTime.Now.Ticks와 Guid.NewGuid (). ToString ()을 사용하여 서로 결합하고 고유 한 ID를 만들 수 있습니다.
DateTime.Now.Ticks가 추가되면 고유 ID가 생성 된 날짜 및 시간 (초)을 확인할 수 있습니다.
코드를 참조하십시오.
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.
고유 ID로 진드기의 일부를 취하고 나중에 참조 할 수 있도록 날짜와 시간을 확인할 수도 있습니다.
파일 이름에 생성 된 고유 ID를 첨부하거나 응용 프로그램 또는 웹 사이트에 사용자의 로그인 로그 아웃을위한 고유 세션 ID를 생성하는 데 사용할 수 있습니다.
Guid.NewGuid (그리고 어떤 경우에는 관심이있을 수있는 "암호 무작위로"아닙니다 그 사실을 무시), 우리는 우리가 약 달리 고유 ID가됩니다 걱정하지 않는 것이 충분히 높은 확률로, 그 주장 할 수 생성-이것은 '틱'보다 훨씬 더 높은 보증 입니다. 따라서, '틱'은 가치가 없으며 여기서 파일 이름에 "보조"데이터를 넣을 것으로 예상됩니다.
나는 보통이 라인을 따라 무언가를한다 :
work.dat1예 :)work.2011-01-15T112357.dat예 :work.2011-01-15T112357.0001.dat예 : GUID를 싫어합니다. 주문 / 예측 가능성을 선호합니다).샘플 클래스는 다음과 같습니다.
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 ;
}
}
알고리즘을 조정하고 싶을 수도 있습니다 (예를 들어 항상 가능한 모든 구성 요소를 파일 이름으로 사용하십시오). 컨텍스트에 따라 달라집니다. 예를 들어 로그 파일을 만드는 중이라면 존재하지 않기를 원한다면 모두 같은 패턴을 이름과 공유하기를 원할 것입니다.
코드가 완벽하지 않습니다 (예 : 전달 된 데이터를 확인하지 않음). 그리고 알고리즘이 완벽하지 않습니다 (하드 드라이브를 채우거나 권한, 실제 I / O 오류 또는 기타 파일 시스템 오류가 발생하면 무한 루프에서 정지됩니다).
Random.Next ()를 사용하여 난수를 생성 할 수도 있습니다. MSDN 링크를 볼 수 있습니다 : http://msdn.microsoft.com/en-us/library/9b3ta19y.aspx
나는 이것을하기 위해 특별히 수업을 썼다. "기본"부분 (기본값은 1 분 단위의 정확한 타임 스탬프)으로 초기화 된 후 고유 한 이름을 만들기 위해 문자를 추가합니다. 따라서 생성 된 첫 번째 스탬프가 1907101215a이면 두 번째 스탬프는 1907101215b, 1907101215c 등이됩니다.
25 개 이상의 고유 스탬프가 필요한 경우 단항 'z'를 사용하여 25를 계산합니다. 따라서 1907101215y, 1907101215za, 1907101215zb, ... 1907101215zy, 1907101215zza, 1907101215zzb 등으로 이동합니다. 그러면 스탬프 뒤의 다음 문자가 문자가 아닌 한 스탬프가 항상 알파벳 순서대로 알파벳 순서대로 정렬됩니다.
스레드 안전하지 않고 시간을 자동으로 업데이트하지 않으며 수백 개의 스탬프가 필요한 경우 빠르게 팽창하지만 내 요구에 충분하다는 것을 알았습니다.
/// <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();
}
}
}
DateTime.Now.Ticks안전하지 않습니다, Guid.NewGuid()당신은 깨끗하고 뭔가해야하는 경우, 너무 못생긴 거의 (안전을 당신이 1ms에서 100 번을 호출하는 경우는 예를 들어 100 % 안전하지 ), 시도 :
Math.Abs(Guid.NewGuid().GetHashCode())
안전하다는 것은 매우 짧은 시간에 몇 ms 동안 그렇게 여러 번 부를 때 독특하게 안전하다는 것을 의미합니다 .
GetHashCode메서드 int는 32 비트 범위를 갖는을 반환 하지만 a GUID는 128 비트 범위를 가지므로 훨씬 더 고유 할 가능성이 높습니다. GUID값 의 형식이 마음에 들지 않으면 간단히 호출 ToString("N")하여 대시를 제거하십시오.