Come posso creare un file temp con una determinata estensione .NET?
-
06-09-2019 - |
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.
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.