Estoy trabajando en un programa que necesita crear varias carpetas temporales para la aplicación. Estos no serán vistos por el usuario. La aplicación está escrita en VB.net. Puedo pensar en algunas maneras de hacerlo, como el nombre de la carpeta incremental o los nombres de las carpetas con números al azar, pero me preguntaba cómo otras personas resuelven este problema.Creación de carpetas temporales
Respuesta
Actualización: Agregado File.Exists comprobar por comentario (2012-Jun-19)
Esto es lo que he usado en VB.NET. Esencialmente el mismo que se presentó, excepto que generalmente no quería crear la carpeta de inmediato.
La ventaja de usar GetRandomFilename es que no crea un archivo, por lo que no tiene que limpiar si usa el nombre para algo que no sea un archivo. Me gusta usarlo para el nombre de la carpeta.
Private Function GetTempFolder() As String
Dim folder As String = Path.Combine(Path.GetTempPath, Path.GetRandomFileName)
Do While Directory.Exists(folder) or File.Exists(folder)
folder = Path.Combine(Path.GetTempPath, Path.GetRandomFileName)
Loop
Return folder
End Function
aleatoria Nombre Ejemplo:
C: \ Documents and Settings \ nombre de usuario \ Configuración local \ Temp \ u3z5e0co.tvq
Aquí hay una variación utilizando un GUID para obtener el nombre de la carpeta temporal.
Private Function GetTempFolderGuid() As String
Dim folder As String = Path.Combine(Path.GetTempPath, Guid.NewGuid.ToString)
Do While Directory.Exists(folder) or File.Exists(folder)
folder = Path.Combine(Path.GetTempPath, Guid.NewGuid.ToString)
Loop
Return folder
End Function
GUID Ejemplo:
C: \ Documents and Settings \ nombre de usuario \ Configuración local \ Temp \ 2dbc6db7-2d45-4b75-B27F-0bd492c60496
Siempre que el nombre de la carpeta no tenga que ser significativo, ¿qué le parece usar un GUID para ellos?
Puede generar un GUID para sus nombres de carpetas temporales.
Puede usar GetTempFileName para crear un archivo temporal , a continuación, elimine y vuelva a crear este archivo como un directorio.
Nota: enlace no funciona, copiar/pegar desde: http://msdn.microsoft.com/en-us/library/aa364991(VS.85).aspx
Usted tiene que usar System.IO.Path.GetTempFileName()
crea un archivo temporal con un nombre único, de cero bytes en el disco y devuelve la ruta completa de ese archivo.
Puede utilizar System.IO.Path.GetDirectoryName(System.IO.Path.GetTempFileName())
para obtener sólo la información de la carpeta temporal, y crear las carpetas de ahí
Se crean en la carpeta Temp de Windows y eso es considerar una buena práctica
Haga ** NO ** haga esto. Llamar a 'System.IO.Path.GetDirectoryName' en' System.IO.Path.GetTempFileName' es el peor reemplazo para 'System.IO.Path.GetTempPath', ya que crea un archivo que se queda atrás. – Jaykul
Algo así como .. .
using System.IO;
string path = Path.GetTempPath() + Path.GetRandomFileName();
while (Directory.Exists(path))
path = Path.GetTempPath() + Path.GetRandomFileName();
Directory.CreateDirectory(path);
quizás con un try-catch para volver a ingresar al bucle si no puede crear el directorio ;-) – Jaykul
respuestas combinadas de @ adam-Wright y pix0r trabajarán el mejor en mi humilde opinión:
using System.IO;
string path = Path.GetTempPath() + Path.GetRandomFileName();
while (Directory.Exists(path))
path = Path.GetTempPath() + Path.GetRandomFileName();
File.Delete(path);
Directory.CreateDirectory(path);
La ventaja de utilizar System.IO.Path.GetTempFileName es que será un archivo en la ruta local del usuario (es decir, no itinerante). Aquí es exactamente donde lo desea para permisos y razones de seguridad.
Solo para aclarar:
System.IO.Path.GetTempPath()
devuelve solo la ruta de la carpeta a la carpeta temporal.
System.IO.Path.GetTempFileName()
devuelve el nombre completo del archivo (incluida la ruta) por lo siguiente:
System.IO.Path.Combine(System.IO.Path.GetTempPath(), System.IO.Path.GetTempFileName())
es redundante.
GetTempPath y GetTempFileName son 2 métodos completamente diferentes. GetTempPath simplemente devuelve la ubicación de la carpeta temporal del sistema, mientras que GetTempFileName crea un archivo temporal de longitud cero y devuelve la ruta completa de ese archivo. –
Hay una posible condición de carrera cuando:
- la creación de un archivo temporal con
GetTempFileName()
, eliminarlo, y hacer una carpeta con el mismo nombre, o - usando
GetRandomFileName()
oGuid.NewGuid.ToString
para nombrar una carpeta y crear la carpeta tarde
con GetTempFileName()
se produce después de la eliminación, otra aplicación podría crear con éxito un archivo temporal con el mismo nombre. El CreateDirectory()
fallaría.
Del mismo modo, entre llamar al GetRandomFileName()
y crear el directorio, otro proceso podría crear un archivo o directorio con el mismo nombre, lo que también daría como resultado CreateDirectory()
.
Para la mayoría de las aplicaciones, está bien que un directorio temporal falle debido a una condición de carrera. Es extremadamente raro después de todo. Para ellos, estas carreras a menudo pueden ser ignoradas.
En el mundo del script de shell de Unix, la creación de archivos y directorios temporales de forma segura y sin carreras es un gran problema. Muchas máquinas tienen usuarios múltiples (hostiles), piense en un host web compartido, y muchos scripts y aplicaciones necesitan crear de forma segura archivos temporales y directorios en el directorio compartido/tmp. Vea Safely Creating Temporary Files in Shell Scripts para una discusión sobre cómo crear de forma segura directorios temporales desde scripts de shell.
Como @JonathanWright pointed out, existen condiciones de carrera para las soluciones:
- crear un archivo temporal con
GetTempFileName()
, eliminarlo, y crear una carpeta con el mismo nombre GetRandomFileName()
uso oGuid.NewGuid.ToString
para crear una nombre de carpeta al azar, verifique si existe y créelo si no.
Es posible, sin embargo, para crear un directorio temporal único atómicamente mediante la utilización de la API Transactional NTFS (TxF).
TxF tiene una función CreateDirectoryTransacted()
que se puede invocar mediante Invocación de plataforma.Para ello, me he adaptado Mohammad Elsheimy's code para llamar CreateFileTransacted()
:
// using System.ComponentModel;
// using System.Runtime.InteropServices;
// using System.Transactions;
[ComImport]
[Guid("79427a2b-f895-40e0-be79-b57dc82ed231")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IKernelTransaction
{
void GetHandle(out IntPtr pHandle);
}
// 2.2 Win32 Error Codes <http://msdn.microsoft.com/en-us/library/cc231199.aspx>
public const int ERROR_PATH_NOT_FOUND = 0x3;
public const int ERROR_ALREADY_EXISTS = 0xb7;
public const int ERROR_EFS_NOT_ALLOWED_IN_TRANSACTION = 0x1aaf;
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool CreateDirectoryTransacted(string lpTemplateDirectory, string lpNewDirectory, IntPtr lpSecurityAttributes, IntPtr hTransaction);
/// <summary>
/// Creates a uniquely-named directory in the directory named by <paramref name="tempPath"/> and returns the path to it.
/// </summary>
/// <param name="tempPath">Path of a directory in which the temporary directory will be created.</param>
/// <returns>The path of the newly-created temporary directory within <paramref name="tempPath"/>.</returns>
public static string GetTempDirectoryName(string tempPath)
{
string retPath;
using (TransactionScope transactionScope = new TransactionScope())
{
IKernelTransaction kernelTransaction = (IKernelTransaction)TransactionInterop.GetDtcTransaction(Transaction.Current);
IntPtr hTransaction;
kernelTransaction.GetHandle(out hTransaction);
while (!CreateDirectoryTransacted(null, retPath = Path.Combine(tempPath, Path.GetRandomFileName()), IntPtr.Zero, hTransaction))
{
int lastWin32Error = Marshal.GetLastWin32Error();
switch (lastWin32Error)
{
case ERROR_ALREADY_EXISTS:
break;
default:
throw new Win32Exception(lastWin32Error);
}
}
transactionScope.Complete();
}
return retPath;
}
/// <summary>
/// Equivalent to <c>GetTempDirectoryName(Path.GetTempPath())</c>.
/// </summary>
/// <seealso cref="GetTempDirectoryName(string)"/>
public static string GetTempDirectoryName()
{
return GetTempDirectoryName(Path.GetTempPath());
}
Dim NewFolder = System.IO.Directory.CreateDirectory(IO.Path.Combine(IO.Path.GetTempPath, Guid.NewGuid.ToString))
@JonathanWright sugiere CreateDirectory fallará cuando ya hay una carpeta. Si leo Directory.CreateDirectory, dice 'Este objeto se devuelve independientemente de si ya existe un directorio en la ruta especificada'. Lo que significa que no se detecta una carpeta creada entre verificar y crear.
Me gusta el CreateDirectoryTransacted() sugerido por @DanielTrebbien pero esta función está obsoleta.
La única solución que veo que queda es utilizar la c api y llamar al 'CreateDirectory' como error si la carpeta existe si realmente necesita asegurarse de cubrir toda la condición de carrera. Eso daría como resultado algo como esto:
Private Function GetTempFolder() As String
Dim folder As String
Dim succes as Boolean = false
Do While not succes
folder = Path.Combine(Path.GetTempPath, Path.GetRandomFileName)
success = c_api_create_directory(folder)
Loop
Return folder
End Function
Una comprobación de bucle infinitamente sería sensato. – Matt
- 1. Creación de cuentas de usuario temporales: Django
- 2. Creación de archivos temporales en bash
- 3. ¿Cómo puedo eliminar carpetas temporales en Windows con R?
- 4. La creación de tablas temporales en procedimiento almacenado de MySQL
- 5. Rieles: creación de archivos temporales de forma portátil
- 6. Creación de archivos temporales en Android con NDK
- 7. Creación de carpetas dentro de un archivo zip en NAnt
- 8. Tablas temporales de PostgreSQL
- 9. temporales C++ rvalue en plantilla
- 10. Innodb y tablas temporales
- 11. Amazon S3 Creación de carpetas a través de SDK .NET a través de Management Console
- 12. Eliminando archivos temporales de ASP.Net
- 13. Intercalación predeterminada de tablas temporales
- 14. Liberación de objetos COM temporales
- 15. Escribiendo datos temporales de R
- 16. Vida útil de los temporales
- 17. Archivos temporales en .Net
- 18. Variables temporales en Mathematica
- 19. Autotools archivos temporales
- 20. ASP.NET - Almacenar archivos temporales
- 21. Bibliotecas temporales para Java
- 22. ¿Cómo lidiar con archivos temporales en ASP.NET?
- 23. Sql server 2008, son tablas temporales únicas
- 24. Tablas temporales en el servidor sql
- 25. Cuentas de correo electrónico temporales para pruebas de integración
- 26. Eliminar carpetas de DDMS
- 27. Última modificación de carpetas
- 28. Seguimiento de archivos/carpetas
- 29. Configuración óptima de tablas temporales de MySQL (tablas de memoria)?
- 30. directorios temporales en WebLogic 10
¿No debería su condición de bucle incluir 'File.Exists' además de' Directory.Exists'? Podría haber un temp_file_ existente en 'Path.GetTempPath', y eso impediría la creación de un directorio. –
Tienes razón. Actualizaré la respuesta para incluir una comprobación de File.Exists() – Rick
Debería ** crear ** la carpeta dentro de la función, por la misma razón que GetTempFileName crea el archivo: para asegurarse de que no hay posibilidad de que alguien más lo haga. – Jaykul