Domanda

Ho bisogno di generare un unico file temporanei con un .estensione csv.

Quello che faccio è

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

Tuttavia, questo non garantisce che il mio .file csv sarà unico.

So che le probabilità che io abbia mai avuto una collisione sono molto bassi (soprattutto se si considera che io non eliminare il .file tmp), ma questo codice non sembra buono per me.

Ovviamente non poteva generare manualmente casuale di nomi di file fino a quando ho trovato finalmente un unico (che non dovrebbe essere un problema), ma sono curioso di sapere se altri hanno trovato un bel modo per affrontare questo problema.

È stato utile?

Soluzione

Garantito per essere (statisticamente) unico nel suo genere:

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

(Per citare l'articolo wiki sul probabilty di una collisione:

  

... proprio rischio annuale di essere colpito da un   meteorite è stimato essere uno   possibilità su 17 miliardi [19], che significa   la probabilità è di circa ,00000000006   (6 × 10-11), equivalente alle probabilità di   creando poche decine di bilioni di   UUID in un anno e avere una   duplicare. In altre parole, solo dopo   generando 1 miliardo di UUID ogni   secondo per i prossimi 100 anni, il   probabilità di creare un solo   duplicare sarebbe di circa il 50%. Il   probabilità di un duplicato sarebbe   circa il 50% se ogni persona sulla terra   possiede 600 milioni UUID

EDIT:. Si prega di consultare anche i commenti di JaredPar

Altri suggerimenti

Prova questa funzione ...

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

Si restituirà un percorso completo con l'estensione della vostra scelta.

Nota, non è garantito per produrre un nome di file univoco in quanto qualcun altro avrebbe potuto tecnicamente già creato quel file. Tuttavia le probabilità che qualcuno indovinare i prossimi GUID prodotte dalla vostra applicazione e la creazione è molto molto basso. E 'abbastanza sicuro di assumere questo sarà unica.

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

Nota: questo funziona come Path.GetTempFileName. Un file vuoto viene creato per riservare il nome del file. Rende 10 tentativi, in caso di urti generati da Path.GetRandomFileName ();

È inoltre possibile utilizzare in alternativa 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");

Qui ho usato l'estensione txt, ma è possibile specificare quello che vuoi. Ho anche impostare il flag mastio su true in modo che il file temporaneo viene mantenuto intorno dopo l'uso. Purtroppo, TempFileCollection crea un file casuale per ogni estensione. Se avete bisogno di più file temporanei, è possibile creare più istanze di TempFileCollection.

Perché non controllare se il file esiste?

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

La documentazione MSDN per C ++ 's GetTempFileName discute la tua preoccupazione e risposte che:

  

GetTempFileName non è in grado di garantire che il nome del file è unico .

     

Solo i 16 bit inferiori del parametro uUnique vengono utilizzati. Questo limita GetTempFileName ad un massimo di 65.535 nomi di file univoci se i parametri lpPathName e lpPrefixString rimangono gli stessi.

     

A causa l'algoritmo utilizzato per generare i nomi dei file, GetTempFileName può eseguire male durante la creazione di un gran numero di file con lo stesso prefisso. In questi casi, si consiglia di si costruisce proprio nome di file basati su GUID .

Come su:

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

E 'altamente improbabile che il computer genera lo stesso GUID nello stesso istante di tempo. L'unico punto debole che vedo qui è la performance DateTime.Now.Ticks impatto aggiungerà.

È inoltre possibile effettuare le seguenti operazioni

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

e anche questo funziona come previsto

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

A mio parere, la maggior parte delle risposte hanno proposto qui come sub-ottimale. Quello proveniente vicino è quello originale proposto inizialmente dal Brann.

Un nome di file Temp deve essere

  • Unique
  • (non esiste già) senza conflitti
  • atomica (Creazione di nome e file nella stessa operazione)
  • difficile da indovinare

A causa di questi requisiti, non è un'idea godd per programmare una bestia da soli. Smart People scrittura IO Libraries preoccuparsi di cose come il blocco (se necessario), ecc Pertanto, non vedo la necessità di riscrivere System.IO.Path.GetTempFileName ().

Questo, anche se sembra goffo, dovrebbe fare il lavoro:

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

Facile funzione in C #:

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

Questo potrebbe essere utile per voi ... E 'per creare una temperatura. cartella e restituire come una stringa in VB.NET.

facilmente convertibili in 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

Questo sembra funzionare bene per me: si verifica la presenza di file di esistenza e crea il file per essere sicuro che sia una posizione scrivibile. Dovrebbe funzionare bene, si può cambiare per tornare direttamente alla FileStream (che normalmente è quello che serve per un file temporaneo):

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

Questo è quello che sto facendo:

string tStamp = String.Format("{0:yyyyMMdd.HHmmss}", DateTime.Now);
string ProcID = Process.GetCurrentProcess().Id.ToString();
string tmpFolder = System.IO.Path.GetTempPath();
string outFile = tmpFolder + ProcID + "_" + tStamp + ".txt";

Questo è un modo semplice ma efficace per generare i nomi dei file incrementali. Si farà il punto della corrente direttamente (si può facilmente rilevare che da qualche altra parte) e cercare i file con la base YourApplicationName * .txt (ancora una volta si può facilmente cambiare la situazione). Si inizierà alle 0000 in modo che il primo nome di file verrà YourApplicationName0000.txt. se per qualche motivo ci sono i nomi di file con spazzatura tra (che significa non numeri) le parti destra e sinistra, i file verranno ignorati in virtù della chiamata 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;
    }

Sulla base delle risposte che ho trovato da internet, vengo al mio codice come segue:

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

E come C # Cookbook da Jay Hilyard, Stephen Teilhet puntata in Utilizzo di un file temporaneo nell'applicazione :

  • è necessario utilizzare un file temporaneo ogni volta che è necessario memorizzare Informazioni temporaneamente per il successivo recupero.

  • L'unica cosa che dovete ricordare è quello di eliminare questo file temporaneo prima che termina l'applicazione che ha creato.

  • Se non viene eliminato, rimarrà nel manuale di temporanea directory fino a quando l'utente elimina manualmente.

Credo che si dovrebbe provare questo:

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

Esso genera un nome di file unico e crea un file con lo stesso nome del file in una posizione specificata.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top