Pregunta

Necesito generar un archivo temporal único con una extensión .csv.

Lo que hago ahora es

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

Sin embargo, esto no garantiza que mi archivo .csv sea único.

Sé que las posibilidades de que alguna vez tenga una colisión son muy bajas (especialmente si considera que no elimino los archivos .tmp), pero este código no me parece bueno.

Por supuesto, podría generar manualmente nombres de archivos aleatorios hasta que finalmente encuentre uno único (lo que no debería ser un problema), pero tengo curiosidad por saber si otros han encontrado una buena manera de solucionar este problema.

¿Fue útil?

Solución

Garantiza que sea (estadísticamente) único:

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

(Citando del artículo de wiki en la probabilty de una colisión:

  

... uno de riesgo anual de ser golpeado por un   meteorito se estima en uno   oportunidad en 17 mil millones [19], lo que significa   la probabilidad es de aproximadamente 0,00000000006   (6 × 10-11), equivalente a las probabilidades de   la creación de unas pocas decenas de billones de   UUID en un año y que tienen una   duplicar. En otras palabras, sólo después de   la generación de 1 mil millones de UUID cada   segundo para los próximos 100 años, la   probabilidad de crear sólo una   duplicar sería de alrededor de 50%. los   probabilidad de un duplicado sería   alrededor del 50% si cada persona en la tierra   es propietaria de 600 millones UUID

EDIT:. Por favor, vea también los comentarios de JaredPar

Otros consejos

Trate de esta función ...

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

Se devolverá una ruta completa con la extensión de su elección.

Tenga en cuenta, que no está garantizado para producir un nombre de archivo único desde que alguien más pudo haber técnicamente ya creado ese archivo. Sin embargo, las posibilidades de que alguien adivine los próximos GUID producidas por su aplicación y creando es muy muy bajo. Es bastante seguro asumir que será único.

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: Esto funciona como Path.GetTempFileName. Un archivo vacío es creado para reservar el nombre del archivo. Se hace 10 intentos, en caso de colisiones generadas por Path.GetRandomFileName ();

También se puede utilizar como 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");

Aquí he utilizado una extensión txt pero se puede especificar lo que quiera. Asimismo, establecer la bandera de mantener a true para que el archivo temporal se mantiene alrededor después de su uso. Por desgracia, TempFileCollection crea un archivo al azar por extensión. Si usted necesita más archivos temporales, puede crear varias instancias de TempFileCollection.

¿Por qué no comprobar si existe el archivo?

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

La documentación de MSDN para GetTempFileName de C++ analiza su inquietud y la responde:

GetTempFileName no puede garantizar que el nombre del archivo sea único.

Sólo se utilizan los 16 bits inferiores del parámetro uUnique.Esto limita GetTempFileName a un máximo de 65.535 nombres de archivos únicos si los parámetros lpPathName y lpPrefixString siguen siendo los mismos.

Debido al algoritmo utilizado para generar nombres de archivos, GetTempFileName puede funcionar mal al crear una gran cantidad de archivos con el mismo prefijo.En esos casos, Se recomienda crear nombres de archivos únicos basados ​​en GUID..

¿Qué hay de:

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

Es altamente improbable que el equipo va a generar el mismo GUID en el mismo instante de tiempo. La única debilidad que veo aquí es el rendimiento de impacto DateTime.Now.Ticks añadirán.

También puede hacer lo siguiente

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

y esto también funciona como se esperaba

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

En mi opinión, la mayoría de las respuestas que se proponen aquí como sub-óptima. El que viene más cercano es el original propuesto inicialmente por Brann.

un nombre de archivo de temperatura debe ser

  • Único
  • (no existe) libre de conflictos
  • Atómica (Creación del nombre del archivo y en la misma operación)
  • difícil de adivinar

Debido a estos requisitos, no es una idea godd para programar una bestia por su cuenta. Las personas inteligentes que escriben IO Libraries se preocupan por cosas como el bloqueo (si es necesario), etc. Por lo tanto, no veo la necesidad de reescribir System.IO.Path.GetTempFileName ().

Esto, incluso si parece torpe, debe hacer el trabajo:

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

Fácil de funciones en C #:

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

Esto podría ser útil para usted ... Es para crear una temp. carpeta y devolverlo como una cadena en VB.NET.

fácilmente convertibles en 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

Esto parece funcionar bien para mí: se comprueba si hay existencia de archivos y crea el archivo para asegurarse de que es una ubicación de escritura. Debería funcionar bien, se puede cambiar para volver directamente a la FileStream (que normalmente es lo que necesita para un archivo temporal):

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

Esto es lo que estoy haciendo:

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

Esta es una manera simple pero eficaz para generar nombres de archivos incrementales. Se verá en la corriente directa (se puede señalar que en otro lugar fácilmente) y la búsqueda de archivos con la base de YourApplicationName * .txt (nuevo se puede cambiar fácilmente eso). Se iniciará en 0000 por lo que se YourApplicationName0000.txt el primer nombre de archivo. si por alguna razón hay nombres de archivo con chatarra entre (es decir, no números) las partes izquierda y derecha, esos archivos serán ignorados en virtud de la llamada 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;
    }

En base a las respuestas que he encontrado a través de Internet, llego a mi código de la siguiente manera:

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

Y como C # libro de cocina por Jay Hilyard, Stephen Teilhet señaló en Uso de un archivo temporal en su aplicación :

  • se debe utilizar un archivo temporal cada vez que necesite para almacenar información de manera temporal para su posterior recuperación.

  • Lo único que debes recordar es eliminar este archivo temporal antes de que se termine la aplicación que lo creó.

  • Si no se elimina, se mantendrá en el usuario del temporal directorio hasta que el usuario elimina manualmente.

Creo que deberías probar esto:

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

Se genera un nombre de archivo único y crea un archivo con ese nombre de archivo en una ubicación especificada.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top