programing

C #에서 임시 파일을 어떻게 자동으로 삭제합니까?

copysource 2021. 1. 16. 20:39
반응형

C #에서 임시 파일을 어떻게 자동으로 삭제합니까?


내 응용 프로그램이 닫히거나 충돌하는 경우 임시 파일을 삭제하는 좋은 방법은 무엇입니까? 이상적으로는 임시 파일을 얻고 사용하고 잊어 버리고 싶습니다.

지금은 임시 파일 목록을 유지하고 Application.ApplicationExit에서 트리거하는 이벤트 처리기로 삭제합니다.

더 좋은 방법이 있습니까?


프로세스가 조기에 종료되면 보장되는 것은 없지만 " using"를 사용 하여이를 수행합니다.

using System;
using System.IO;
sealed class TempFile : IDisposable
{
    string path;
    public TempFile() : this(System.IO.Path.GetTempFileName()) { }

    public TempFile(string path)
    {
        if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path");
        this.path = path;
    }
    public string Path
    {
        get
        {
            if (path == null) throw new ObjectDisposedException(GetType().Name);
            return path;
        }
    }
    ~TempFile() { Dispose(false); }
    public void Dispose() { Dispose(true); }
    private void Dispose(bool disposing)
    {
        if (disposing)
        {
            GC.SuppressFinalize(this);                
        }
        if (path != null)
        {
            try { File.Delete(path); }
            catch { } // best effort
            path = null;
        }
    }
}
static class Program
{
    static void Main()
    {
        string path;
        using (var tmp = new TempFile())
        {
            path = tmp.Path;
            Console.WriteLine(File.Exists(path));
        }
        Console.WriteLine(File.Exists(path));
    }
}

이제 TempFile가 폐기되거나 가비지 수집되면 파일이 삭제됩니다 (가능한 경우). 당신은 분명히 이것을 당신이 좋아하는 범위 나 어딘가의 컬렉션에서 사용할 수 있습니다.


FileOptions.DeleteOnClose 플래그 사용을 고려하십시오.

using (FileStream fs = new FileStream(Path.GetTempFileName(),
       FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None,
       4096, FileOptions.RandomAccess | FileOptions.DeleteOnClose))
{
    // temp file exists
}

// temp file is gone

P / InvokeCreateFileFILE_FLAG_DELETE_ON_CLOSE플래그를 전달할 있습니다. 모든 핸들이 닫히면 Windows에 파일을 삭제하도록 지시합니다. 참조 : Win32 CreateFile문서 .


TempFileCollection이전 버전의 .NET에서 사용할 수있는 내장 된 .NET 클래스를 사용하고 IDisposable인터페이스를 구현 하므로 "using"키워드 와 함께 사용하면 자체적으로 정리됩니다 .

다음은 포함 된 리소스에서 텍스트를 추출하는 예입니다 (여기에 설명 된대로 프로젝트 속성 페이지-> 리소스 탭을 통해 추가됨 : .NET 어셈블리에 텍스트 파일을 포함하는 방법? , 그런 다음 "EmbeddedResource"포함 된 파일의 속성 설정에서로 설정 됨).

    // Extracts the contents of the embedded file, writes them to a temp file, executes it, and cleans up automatically on exit.
    private void ExtractAndRunMyScript()
    {
        string vbsFilePath;

        // By default, TempFileCollection cleans up after itself.
        using (var tempFiles = new System.CodeDom.Compiler.TempFileCollection())
        {
            vbsFilePath= tempFiles.AddExtension("vbs");

            // Using IntelliSense will display the name, but it's the file name
            // minus its extension.
            System.IO.File.WriteAllText(vbsFilePath, global::Instrumentation.Properties.Resources.MyEmbeddedFileNameWithoutExtension);

            RunMyScript(vbsFilePath);
        }

        System.Diagnostics.Debug.Assert(!File.Exists(vbsFilePath), @"Temp file """ + vbsFilePath+ @""" has not been deleted.");
    }

저는 주로 C # 프로그래머는 아니지만 C ++에서는 RAII사용 합니다. C # 온라인 에서 RAII와 유사한 동작을 사용하는 방법에 대한 몇 가지 힌트가 있지만 대부분은 결정적이지 않은 종료자를 사용하는 것 같습니다.

임시 파일을 생성하는 Windows SDK 기능이 있다고 생각하지만 프로그램 종료시 자동으로 삭제되는지 모르겠습니다. 있다 GetTempPath의 기능을하지만, IIRC를 다시 시작을하거나 로그인 할 때 파일은이 삭제됩니다.

추신 : C # 소멸자 문서에 따르면 리소스를 해제 할 수 있고 해제해야합니다. 그렇다면 소멸자에서 임시 파일을 간단히 삭제할 수 있지만 다시 말하지만 완전히 결정적이지 않을 수 있습니다.


Its nice to see that you want to be responsible, but if the files aren't huge (>50MB) you would be in line with everyone (MS included) in leaving them in the temp directory. Disk space is abundant.

As csl posted, the GetTempPath is the way to go. Users who are short on space will be able to run disk cleanup and your files (along with everyone else's) will be cleaned up.


I use a more reliable solution:

using System.IO;
using System.Reflection;

namespace Konard.Helpers
{
    public static partial class TemporaryFiles
    {
        private const string UserFilesListFilenamePrefix = ".used-temporary-files.txt";
        static private readonly object UsedFilesListLock = new object();

        private static string GetUsedFilesListFilename()
        {
            return Assembly.GetEntryAssembly().Location + UserFilesListFilenamePrefix;
        }

        private static void AddToUsedFilesList(string filename)
        {
            lock (UsedFilesListLock)
            {
                using (var writer = File.AppendText(GetUsedFilesListFilename()))
                    writer.WriteLine(filename);
            }
        }

        public static string UseNew()
        {
            var filename = Path.GetTempFileName();
            AddToUsedFilesList(filename);
            return filename;
        }

        public static void DeleteAllPreviouslyUsed()
        {
            lock (UsedFilesListLock)
            {
                var usedFilesListFilename = GetUsedFilesListFilename();

                if (!File.Exists(usedFilesListFilename))
                    return;

                using (var listFile = File.Open(usedFilesListFilename, FileMode.Open))
                {
                    using (var reader = new StreamReader(listFile))
                    {
                        string tempFileToDelete;
                        while ((tempFileToDelete = reader.ReadLine()) != null)
                        {
                            if (File.Exists(tempFileToDelete))
                                File.Delete(tempFileToDelete);
                        }
                    }
                }

                // Clean up
                using (File.Open(usedFilesListFilename, FileMode.Truncate)) { }
            }
        }
    }
}

Every time you need temporary file use:

var tempFile = TemporaryFiles.UseNew();

To be sure all temporary files are deleted after application closes or crashes put

TemporaryFiles.DeleteAllPreviouslyUsed();

at start of the application.


You could launch a thread on startup that will delete files that exist when they "shouldn't" to recover from your crash.


If you're building a Windows Forms Application, you can use this code:

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        File.Delete("temp.data");
    }

ReferenceURL : https://stackoverflow.com/questions/400140/how-do-i-automatically-delete-tempfiles-in-c

반응형