2010-11-05 5 views
10

¿Cómo puedo portably (estoy interesado principalmente en Windows y Linux) generar un nuevo nombre de archivo en un directorio especificado, con prefijo y sufijo de nombre de archivo especificado?Generación portátil de un nuevo nombre de archivo en un directorio especificado

std::string UniqueName(std::string const& dir, std::string const& prefix, 
         std::string const& suffix); 

Cualquier sugerencia para implementar esta función, con la menor cantidad posible de dependencias explícitas en plataformas específicas.

+2

¿En qué plataforma/sistema operativo? No hay una forma pura de C++ para lograr esto. –

+2

¿Qué significa "único"? ¿Único a tu programa? Único en un directorio dado?Único en una computadora determinada? –

+0

Use la marca de tiempo, cuando se creará el archivo. – DumbCoder

Respuesta

19

Tenga en cuenta que hacer esto mal es un problema de seguridad. Hay trucos para explotar archivos temporales (ish), y estos pueden darle acceso de administrador a todo el sistema, no solo a su aplicación. Ver this para algunos consejos.

Un par de maneras de hacer esto:

  • Siempre que sea posible, utilice las funciones de biblioteca proporcionados en lugar de escribir el suyo propio. Por ejemplo, en Windows use GetTempFileName, en Linux use mkstemp.
  • Use boost::filesystem::unique_path, que le permite generar de manera confiable nombres de archivos únicos de acuerdo con una plantilla que usted proporcione.

boost::filesystem está programado para convertirse en una parte de C++ TR2, que debe ser apoyado por casi todos los compiladores en el futuro. Tenga en cuenta que debe #define BOOST_FILESYSTEM_VERSION 3 (info), de lo contrario obtendrá una versión anterior de boost::filesystem que no admite unique_path.

2

Puede generar un UUID para crear nombres únicos. Consulte this link para obtener una lista de implementaciones en C++.

1

Para una solución ventanas, Generate a guid y usarlo como nombre de archivo

Este es el código para generar el GUID para que pueda empezar.

_TUCHAR *guidStr = 0x00; 
GUID *pguid = 0x00; 
pguid = new GUID; 
CoCreateGuid(pguid); 
// Convert the GUID to a string 
UuidToString(pguid, &guidStr); 
delete pguid; 
+5

¿Por qué usar '0x00' en lugar de' 0'? Eso es bastante poco ortodoxo. Y solo crea 'pguid' sin asignación automática, no asignación dinámica. Por lo menos, use 'auto_ptr'. – GManNickG

+0

@GMan Esto es solo un bloque de código que utilicé para algunas codificaciones de R & D (Ripoff y despliegue). Realmente no he profundizado en C++ durante años. Siéntase libre de editar mi publicación para que sea más correcta para los estándares de codificación modernos. –

+0

Si busca una solución específica de Windows, quizás prefiera usar [GetTempFileName] (http://msdn.microsoft.com/en-us/library/aa364991%28VS.85%29.aspx). –

0

La función, dada la firma que tiene, es imposible de implementar a la perfección. Con los sistemas de ficheros, que muy a menudo tiene el problema de las condiciones de carrera:

  • Sus funciones decide sobre un nombre de archivo "foobar"
  • Otra persona crea el archivo "foobar"
  • Su programa no se puede abrir "foobar "porque alguien más en el paso 2 te golpeó.

Las máquinas POSIX tienen una función para evitar esto: mkstemp. Desafortunadamente, no hay un equivalente de Windows para esto. En Windows, use GetTempFileName, que está más cerca de mktemp, pero use CREATE_NEW cuando llame al CreateFile, lo que causará que CreateFile falle si el archivo existe. A partir de ahí, puede implementar una versión de Windows de mkstemp.

0

código no probado, pero yo uso algo muy similar en un par proyecta

std::string UniqueName(std::string const& dir = _T(""), std::string const& prefix = _T(""), std::string const& suffix = _T("")) 
{ 
    std::string retVal = _T(""); 

    std::string sDirectory = boost::filesystem::temp_directory_path().string(); 

    if (! dir.empty()) 
     sDirectory = dir; 

    std::string sFilesName = _T("%%%%-%%%%-%%%%-%%%%"); 

    if (! prefix.empty()) 
     sFilesName = prefix; 

    boost::format fmter(_T("%s%s%s")); 
    std::string sModel = boost::str (boost::format (fmter 
     % sDirectory 
     % sFilesName 
     % suffix)); 

    boost::filesystem::path temp = boost::filesystem::unique_path(sModel); 
    retVal = temp.string(); 

    return retVal; 
} 
Cuestiones relacionadas