← Назад к вопросам

Каким образом можно создать файл только если его нет?

1.2 Junior🔥 291 комментариев
#Qt и GUI#STL контейнеры и алгоритмы

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Каким образом можно создать файл только если его нет?

В C++ есть несколько способов создать файл только если он не существует. Выбор зависит от платформы и требований.

1. POSIX: open() с флагами O_CREAT и O_EXCL

Это атомарная операция — либо создаёт файл, либо ошибка:

#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>

int createFileIfNotExists(const char* filename) {
    // O_CREAT: создать если не существует
    // O_EXCL: ошибка если существует
    // O_WRONLY: открыть на запись
    int fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, 0644);
    
    if (fd == -1) {
        if (errno == EEXIST) {
            std::cerr << "File already exists\n";
        } else {
            perror("open failed");
        }
        return -1;
    }
    // fd содержит файловый дескриптор
    close(fd);
    return 0;
}

Преимущества: Атомарный, работает везде, низкий уровень.

Недостатки: Нужно проверять errno, низкоуровневый API.

2. C++17: std::filesystem

Модерный и кроссплатформенный способ:

#include <filesystem>

bool createFileIfNotExists(const std::string& filename) {
    namespace fs = std::filesystem;
    
    // Проверяем существует ли файл
    if (fs::exists(filename)) {
        std::cerr << "File already exists\n";
        return false;
    }
    
    // Создаём пустой файл
    std::ofstream file(filename);
    if (!file) {
        std::cerr << "Failed to create file\n";
        return false;
    }
    
    return true;
}

Проблема: Между exists() и ofstream может быть race condition (TOCTOU).

Лучше: Использовать try-catch с исключением:

bool createFileIfNotExists(const std::string& filename) {
    namespace fs = std::filesystem;
    
    try {
        // Создаём файл, выбросит исключение если уже существует
        std::ofstream file(filename);
        if (!file.is_open()) {
            throw std::runtime_error("Cannot create file");
        }
        return true;
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << "\n";
        return false;
    }
}

3. C++17: std::filesystem::create_directories() с status

#include <filesystem>

bool createFileIfNotExists(const std::string& filename) {
    namespace fs = std::filesystem;
    
    std::error_code ec;
    
    // Проверяем существует ли
    auto status = fs::status(filename, ec);
    if (!ec && fs::exists(status)) {
        return false;  // Существует
    }
    
    // Создаём
    std::ofstream file(filename);
    return file.is_open();
}

4. Windows: CreateFileA() с CREATE_NEW

#include <windows.h>

bool createFileIfNotExists(const char* filename) {
    // CREATE_NEW: ошибка если существует
    HANDLE hFile = CreateFileA(
        filename,
        GENERIC_WRITE,
        0,  // Не делиться
        NULL,
        CREATE_NEW,  // Создать, ошибка если существует
        FILE_ATTRIBUTE_NORMAL,
        NULL
    );
    
    if (hFile == INVALID_HANDLE_VALUE) {
        if (GetLastError() == ERROR_FILE_EXISTS) {
            std::cerr << "File already exists\n";
        }
        return false;
    }
    
    CloseHandle(hFile);
    return true;
}

5. Простой C++ способ (не атомарный)

#include <fstream>
#include <filesystem>

bool createFileIfNotExists(const std::string& filename) {
    if (std::filesystem::exists(filename)) {
        return false;  // Файл существует
    }
    
    std::ofstream file(filename);
    return file.is_open();
}

Внимание: Есть race condition! Между exists() и ofstream() другой процесс может создать файл.

Сравнение методов

МетодПлатформаАтомарныйПростота
open() O_EXCLPOSIXДаСредняя
std::filesystemВсе (C++17)НетВысокая
CreateFileA()WindowsДаСредняя
std::ofstreamВсеНетВысокая

Мой рекомендация

Если доступен C++17: Используй std::filesystem с проверкой.

Если нужна атомарность: Используй POSIX open() с O_EXCL или Windows CreateFile().

Если простота и нет race condition'а: Используй std::ofstream.

Для production кода всегда используй атомарные операции, чтобы избежать race conditions.