Переносное создание нового имени файла в указанной директории

Как я могу переносимо (меня больше всего интересуют окна и linux) генерируют новое имя файла в указанной директории с указанным префиксом имени файла и суффиксом?

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

Любые предложения по реализации этой функции с максимально возможными явными зависимостями от определенных платформ.

Ответ 1

Имейте в виду, что делать это неправильно - это дыра в безопасности. Есть трюки для использования временных (ish) файлов, и они могут предоставить Администратору доступ ко всей системе, а не только к вашему приложению. См. этот для некоторых советов.

Несколько способов сделать это:

  • По возможности используйте функции, предоставляемые библиотекой, вместо того, чтобы писать свои собственные. Например, в Windows используйте GetTempFileName, в Linux используйте mkstemp.
  • Используйте boost::filesystem::unique_path, который позволяет надежно генерировать уникальные имена файлов в соответствии с предоставленным вами шаблоном.

boost::filesystem планируется стать частью С++ TR2, который должен поддерживаться почти всеми компиляторами в будущем. Обратите внимание, что вы должны #define BOOST_FILESYSTEM_VERSION 3 (info), в противном случае вы получите более старую версию boost::filesystem, которая не поддерживает unique_path.

Ответ 2

Вы можете создать UUID для создания уникальных имен. См. эту ссылку для списка реализаций на С++.

Ответ 3

Для решения Windows Сгенерируйте руководство и используйте его как имя файла

Вот код для генерации руководства, чтобы вы начали.

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

Ответ 4

Функция, с учетом вашей подписи, невозможно реализовать отлично. С файловыми системами у вас очень часто возникает проблема условий гонки:

  • Ваши функции определяют имя файла "foobar"
  • Кто-то еще создает файл "foobar"
  • Ваша программа не может открыть "foobar" , потому что кто-то еще на шаге 2 победил вас.

У машин POSIX есть функция, чтобы обойти это: mkstemp. К сожалению, для Windows нет эквивалента Windows. В Windows используйте GetTempFileName, который ближе к mktemp, но используйте CREATE_NEW при вызове CreateFile, что вызовет CreateFile, если файл существует. Оттуда вы можете реализовать версию Windows mkstemp.

Ответ 5

непроверенный код, но я использую что-то очень похожее в нескольких проектах

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