IT

.NET으로 특정 확장자를 가진 임시 파일을 어떻게 만들 수 있습니까?

lottoking 2020. 3. 31. 08:27
반응형

.NET으로 특정 확장자를 가진 임시 파일을 어떻게 만들 수 있습니까?


확장명이 .csv 인 고유 한 임시 파일을 생성해야합니다.

내가 지금하는 일은

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

그러나 이것이 내 .csv 파일이 고유하다는 것을 보장하지는 않습니다.

충돌 가능성이 매우 낮다는 것을 알고 있습니다 (특히 .tmp 파일을 삭제하지 않는다고 생각하면).이 코드는 나에게 좋지 않습니다.

물론 문제가되지 않아야하는 고유 한 파일을 찾을 때까지 임의의 파일 이름을 수동으로 생성 할 수 있지만 다른 사람들이이 문제를 처리 할 수있는 좋은 방법을 찾았는지 궁금합니다.


(통계적으로) 고유해야합니다.

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

(충돌 확률에 대한 위키 기사에서 인용하려면 :

... 운석에 부딪 힐 수있는 연간 위험은 170 억으로 한 번의 확률로 추정됩니다 [19]. 이는 확률이 약 0.00000000006 (6 × 10-11)이며 이는 수십 1 년에 수 조조의 UUID가 있으며 하나의 복제본이 있습니다. 다시 말해, 향후 100 년 동안 초당 10 억 개의 UUID를 생성 한 후에 만 ​​하나의 복제본을 생성 할 확률은 약 50 %입니다. 지구상의 모든 사람이 6 억 UUID를 소유하고 있다면 한 번의 복제 확률은 약 50 %입니다.

편집 : JaredPar의 의견도 참조하십시오.


이 기능을 사용해보십시오 ...

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

선택한 확장자로 전체 경로를 반환합니다.

다른 사람이 기술적으로 해당 파일을 이미 만들었을 수 있으므로 고유 한 파일 이름을 생성 할 수는 없습니다. 그러나 누군가가 앱에서 생성 한 다음 guid를 추측하여 만들 가능성은 매우 낮습니다. 이것이 독특하다고 가정하는 것이 안전합니다.


public static string GetTempFileName(string extension)
{
  int attempt = 0;
  while (true)
  {
    string fileName = Path.GetRandomFileName();
    fileName = Path.ChangeExtension(fileName, extension);
    fileName = Path.Combine(Path.GetTempPath(), fileName);

    try
    {
      using (new FileStream(fileName, FileMode.CreateNew)) { }
      return fileName;
    }
    catch (IOException ex)
    {
      if (++attempt == 10)
        throw new IOException("No unique temporary file name is available.", ex);
    }
  }
}

참고 : 이것은 Path.GetTempFileName과 같이 작동합니다. 파일 이름을 예약하기 위해 빈 파일이 작성됩니다. Path.GetRandomFileName ()에 의해 생성 된 충돌의 경우 10 회 시도합니다.


또는 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");

여기서는 txt 확장자를 사용했지만 원하는 것을 지정할 수 있습니다. 또한 사용 후 임시 파일이 유지되도록 keep 플래그를 true로 설정했습니다. 불행히도 TempFileCollection은 확장명마다 하나의 임의 파일을 만듭니다. 임시 파일이 더 필요한 경우 TempFileCollection의 여러 인스턴스를 만들 수 있습니다.


파일이 존재하는지 확인하지 않는 이유는 무엇입니까?

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

C ++의 GetTempFileName에 대한 MSDN 설명서 는 사용자의 우려 사항을 설명하고 이에 대한 답변을 제공합니다.

GetTempFileName은 파일 이름이 고유하다는 것을 보장 할 수 없습니다 .

uUnique 매개 변수의 하위 16 비트 만 사용됩니다. lpPathName 및 lpPrefixString 매개 변수가 동일하게 유지되면 GetTempFileName을 최대 65,535 개의 고유 파일 이름으로 제한합니다.

파일 이름을 생성하는 데 사용 된 알고리즘으로 인해 동일한 접두사를 가진 많은 수의 파일을 만들 때 GetTempFileName의 성능이 저하 될 수 있습니다. 이러한 경우 GUID를 기반으로 고유 한 파일 이름을 구성하는 것이 좋습니다 .


어때요?

Path.Combine(Path.GetTempPath(), DateTime.Now.Ticks.ToString() + "_" + Guid.NewGuid().ToString() + ".csv")

컴퓨터가 동일한 순간에 동일한 Guid를 생성하는 것은 매우 불가능합니다. 내가 볼 수있는 유일한 약점은 DateTime.Now.Ticks에 성능 영향이 있다는 것입니다.


다음을 수행 할 수도 있습니다.

string filename = Path.ChangeExtension(Path.GetTempFileName(), ".csv");

그리고 이것은 또한 예상대로 작동합니다

string filename = Path.ChangeExtension(Path.GetTempPath() + Guid.NewGuid().ToString(), ".csv");

내 의견으로는, 대부분의 답변은 여기에 차선책으로 제안되었습니다. 가장 가까운 것은 Brann이 처음 제안한 것입니다.

임시 파일 이름은

  • 독특한
  • 충돌이 없음 (아직 존재하지 않음)
  • 원자 (같은 작업으로 이름과 파일 생성)
  • 추측하기 어렵다

이러한 요구 사항 때문에 그러한 짐승을 스스로 프로그래밍하는 것은 신의 생각이 아닙니다. IO 라이브러리를 작성하는 똑똑한 사람들은 (필요한 경우) 잠금과 같은 것에 대해 걱정합니다. 따라서 System.IO.Path.GetTempFileName ()을 다시 작성할 필요가 없습니다.

서투른 것처럼 보이더라도 작업을 수행해야합니다.

//Note that this already *creates* the file
string filename1 = System.IO.Path.GetTempFileName()
// Rename and move
filename = filename.Replace(".tmp", ".csv");
File.Move(filename1 , filename);

C #의 쉬운 기능 :

public static string GetTempFileName(string extension = "csv")
{
    return Path.ChangeExtension(Path.GetTempFileName(), extension);
}

이것은 당신에게 도움이 될 수 있습니다 ... 그것은 임시 직원을 만드는 것입니다. 폴더에 넣고 VB.NET에서 문자열로 반환하십시오.

C #으로 쉽게 변환 가능 :

Public Function GetTempDirectory() As String
    Dim mpath As String
    Do
        mpath = System.IO.Path.Combine(System.IO.Path.GetTempPath, System.IO.Path.GetRandomFileName)
    Loop While System.IO.Directory.Exists(mpath) Or System.IO.File.Exists(mpath)
    System.IO.Directory.CreateDirectory(mpath)
    Return mpath
End Function

이것은 나에게 잘 작동하는 것 같습니다 : 파일 존재 여부를 확인하고 파일이 쓰기 가능한 위치인지 확인합니다. 제대로 작동하면 FileStream (일반적으로 임시 파일에 필요한 것)을 직접 반환하도록 변경할 수 있습니다.

private string GetTempFile(string fileExtension)
{
  string temp = System.IO.Path.GetTempPath();
  string res = string.Empty;
  while (true) {
    res = string.Format("{0}.{1}", Guid.NewGuid().ToString(), fileExtension);
    res = System.IO.Path.Combine(temp, res);
    if (!System.IO.File.Exists(res)) {
      try {
        System.IO.FileStream s = System.IO.File.Create(res);
        s.Close();
        break;
      }
      catch (Exception) {

      }
    }
  }
  return res;
} // GetTempFile

이것이 내가하고있는 일입니다.

문자열 tStamp = String.Format ( "{0 : yyyyMMdd.HHmmss}", DateTime.Now);
문자열 ProcID = Process.GetCurrentProcess (). Id.ToString ();
문자열 tmpFolder = System.IO.Path.GetTempPath ();
문자열 출력 파일 = tmpFolder + ProcID + "_"+ tStamp + ".txt";

이는 증분 파일 이름을 생성하는 간단하지만 효과적인 방법입니다. 현재를 직접보고 (다른 곳을 쉽게 가리킬 수 있음) 기본 YourApplicationName * .txt를 사용하여 파일을 검색합니다 (다시 쉽게 변경할 수 있음). 첫 번째 파일 이름이 YourApplicationName0000.txt가되도록 0000에서 시작합니다. 어떤 이유로 든 왼쪽과 오른쪽 부분 사이에 정크가있는 파일 이름 (숫자가 아님)이있는 경우 tryparse 호출로 인해 해당 파일이 무시됩니다.

    public static string CreateNewOutPutFile()
    {
        const string RemoveLeft = "YourApplicationName";
        const string RemoveRight = ".txt";
        const string searchString = RemoveLeft + "*" + RemoveRight;
        const string numberSpecifier = "0000";

        int maxTempNdx = -1;

        string fileName;
        string [] Files = Directory.GetFiles(Directory.GetCurrentDirectory(), searchString);
        foreach( string file in Files)
        {
            fileName = Path.GetFileName(file);
            string stripped = fileName.Remove(fileName.Length - RemoveRight.Length, RemoveRight.Length).Remove(0, RemoveLeft.Length);
            if( int.TryParse(stripped,out int current) )
            {
                if (current > maxTempNdx)
                    maxTempNdx = current;
            }
        }
        maxTempNdx++;
        fileName = RemoveLeft + maxTempNdx.ToString(numberSpecifier) + RemoveRight;
        File.CreateText(fileName); // optional
        return fileName;
    }

인터넷에서 찾은 답변을 바탕으로 다음과 같이 코드를 작성합니다.

public static string GetTemporaryFileName()
{       
    string tempFilePath = Path.Combine(Path.GetTempPath(), "SnapshotTemp");
    Directory.Delete(tempFilePath, true);
    Directory.CreateDirectory(tempFilePath);
    return Path.Combine(tempFilePath, DateTime.Now.ToString("MMddHHmm") + "-" + Guid.NewGuid().ToString() + ".png");
}

Jay Hilyard의 C # Cookbook으로서 Stephen Teilhet은 애플리케이션에서 임시 파일 사용을 지적했습니다 .

  • 나중에 검색하기 위해 정보를 임시로 저장해야 할 때마다 임시 파일을 사용해야합니다.

  • 기억해야 할 것은 파일을 만든 응용 프로그램이 종료되기 전에이 임시 파일을 삭제하는 것입니다.

  • 삭제되지 않으면 사용자가 수동으로 삭제할 때까지 사용자의 임시 디렉토리에 남아 있습니다.


나는 당신이 이것을 시도해야한다고 생각합니다 :

string path = Path.GetRandomFileName();
path = Path.Combine(@"c:\temp", path);
path = Path.ChangeExtension(path, ".tmp");
File.Create(path);

고유 한 파일 이름을 생성하고 지정된 위치에 해당 파일 이름을 가진 파일을 작성합니다.

참고 URL : https://stackoverflow.com/questions/581570/how-can-i-create-a-temp-file-with-a-specific-extension-with-net

반응형