C++ File Operations | 'File Operations' Guide

C++ File Operations | 'File Operations' Guide

이 글의 핵심

C++ File Operations: "File Operations" Guide. Basic file operations and directory operations.

Introduction

C++17 <filesystem> library provides standard API for file and directory manipulation. Replaces platform-specific APIs (POSIX, Windows API) to write portable code.


1. Basic File Operations

Basic Setup

Here is detailed implementation code using C++. Import necessary modules, perform branching with conditionals. Understand the role of each part while examining the code.

#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

int main() {
    // Check file existence
    if (fs::exists("test.txt")) {
        std::cout << "File exists" << std::endl;
    }
    
    // File size
    auto size = fs::file_size("test.txt");
    std::cout << "Size: " << size << " bytes" << std::endl;
    
    return 0;
}

File Copy

Below is an implementation example using C++. Understand the role of each part while examining the code.

// Basic copy
fs::copy_file("src.txt", "dst.txt");

// Overwrite
fs::copy_file("src.txt", "dst.txt", 
              fs::copy_options::overwrite_existing);

// Directory copy (recursive)
fs::copy("src_dir", "dst_dir", 
         fs::copy_options::recursive);

File Move and Delete

Below is an implementation example using C++. Try running the code directly to check its operation.

// Rename (move)
fs::rename("old.txt", "new.txt");

// Delete file
fs::remove("file.txt");

// Delete directory (recursive)
fs::remove_all("dir");

2. Directory Operations

Directory Creation

Below is an implementation example using C++. Perform branching with conditionals. Understand the role of each part while examining the code.

// Single directory
fs::create_directory("mydir");

// Nested directory (recursive)
fs::create_directories("path/to/dir");

// Returns false if already exists
bool created = fs::create_directory("existing_dir");
if (!created) {
    std::cout << "Already exists or creation failed" << std::endl;
}

Directory Traversal

Here is detailed implementation code using C++. Import necessary modules, ensure stability through error handling, process data with loops, perform branching with conditionals. Understand the role of each part while examining the code.

#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

int main() {
    // Traverse current directory
    for (const auto& entry : fs::directory_iterator(".")) {
        std::cout << entry.path() << std::endl;
    }
    
    // Recursive traversal
    for (const auto& entry : fs::recursive_directory_iterator(".")) {
        if (entry.is_regular_file()) {
            std::cout << "File: " << entry.path() << std::endl;
        } else if (entry.is_directory()) {
            std::cout << "Directory: " << entry.path() << std::endl;
        }
    }
    
    return 0;
}

3. Copy Options

copy_options Flags

Here is detailed implementation code using C++. Import necessary modules. Understand the role of each part while examining the code.

#include <filesystem>

namespace fs = std::filesystem;

// Default: error if already exists
fs::copy_file("src.txt", "dst.txt");

// Overwrite
fs::copy_file("src.txt", "dst.txt",
              fs::copy_options::overwrite_existing);

// Skip (ignore if exists)
fs::copy_file("src.txt", "dst.txt",
              fs::copy_options::skip_existing);

// Update (copy if newer)
fs::copy_file("src.txt", "dst.txt",
              fs::copy_options::update_existing);

// Recursive copy (directory)
fs::copy("src_dir", "dst_dir",
         fs::copy_options::recursive);

// Copy symbolic link (link itself)
fs::copy("link", "new_link",
         fs::copy_options::copy_symlinks);

copy_options Combination:

Here is a simple C++ code example. Try running the code directly to check its operation.

// Recursive + overwrite
fs::copy("src_dir", "dst_dir",
         fs::copy_options::recursive | 
         fs::copy_options::overwrite_existing);

4. Practical Examples

Example 1: Safe File Copy

Here is detailed implementation code using C++. Import necessary modules, perform work efficiently through async processing, ensure stability through error handling, perform branching with conditionals. Understand the role of each part while examining the code.

#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

bool copyFileSafe(const fs::path& src, const fs::path& dst) {
    try {
        // Check source file exists
        if (!fs::exists(src)) {
            std::cerr << "Source file does not exist: " << src << std::endl;
            return false;
        }
        
        // Create destination directory
        fs::create_directories(dst.parent_path());
        
        // Copy file
        fs::copy_file(src, dst, 
                      fs::copy_options::overwrite_existing);
        
        std::cout << "Copy complete: " << src << " -> " << dst << std::endl;
        return true;
        
    } catch (const fs::filesystem_error& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return false;
    }
}

int main() {
    copyFileSafe("data/input.txt", "backup/input.txt");
    return 0;
}

Example 2: Directory Backup

Here is the backupDirectory implementation:

#include <filesystem>
#include <iostream>
#include <chrono>
#include <iomanip>
#include <sstream>

namespace fs = std::filesystem;

std::string getCurrentTimestamp() {
    auto now = std::chrono::system_clock::now();
    auto time = std::chrono::system_clock::to_time_t(now);
    
    std::stringstream ss;
    ss << std::put_time(std::localtime(&time), "%Y%m%d_%H%M%S");
    return ss.str();
}

void backupDirectory(const fs::path& src, const fs::path& backupRoot) {
    try {
        // Create backup directory with timestamp
        fs::path backupPath = backupRoot / (src.filename().string() + "_" + getCurrentTimestamp());
        
        // Recursive copy
        fs::copy(src, backupPath, 
                 fs::copy_options::recursive | 
                 fs::copy_options::overwrite_existing);
        
        std::cout << "Backup complete: " << backupPath << std::endl;
        
    } catch (const fs::filesystem_error& e) {
        std::cerr << "Backup failed: " << e.what() << std::endl;
    }
}

int main() {
    backupDirectory("project", "backups");
    // Result: backups/project_20260329_143025/
    return 0;
}

Example 3: Clean Old Files

Here is detailed implementation code using C++. Import necessary modules, perform work efficiently through async processing, ensure stability through error handling, process data with loops, perform branching with conditionals. Understand the role of each part while examining the code.

#include <filesystem>
#include <iostream>
#include <chrono>

namespace fs = std::filesystem;

void cleanupOldFiles(const fs::path& dir, int days) {
    try {
        auto now = fs::file_time_type::clock::now();
        auto threshold = now - std::chrono::hours(24 * days);
        
        int deletedCount = 0;
        
        for (const auto& entry : fs::directory_iterator(dir)) {
            if (entry.is_regular_file()) {
                auto mtime = fs::last_write_time(entry);
                
                if (mtime < threshold) {
                    auto size = fs::file_size(entry);
                    fs::remove(entry.path());
                    
                    std::cout << "Deleted: " << entry.path() 
                              << " (" << size << " bytes)" << std::endl;
                    deletedCount++;
                }
            }
        }
        
        std::cout << "Total " << deletedCount << " files deleted" << std::endl;
        
    } catch (const fs::filesystem_error& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }
}

int main() {
    cleanupOldFiles("temp", 7);  // Delete files older than 7 days
    return 0;
}

Example 4: File Synchronization

Here is detailed implementation code using C++. Import necessary modules, perform work efficiently through async processing, ensure stability through error handling, process data with loops, perform branching with conditionals. Understand the role of each part while examining the code.

#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

void syncDirectories(const fs::path& src, const fs::path& dst) {
    try {
        for (const auto& entry : fs::recursive_directory_iterator(src)) {
            auto relativePath = fs::relative(entry.path(), src);
            auto dstPath = dst / relativePath;
            
            if (entry.is_directory()) {
                // Create directory
                fs::create_directories(dstPath);
            } else if (entry.is_regular_file()) {
                // Copy if doesn't exist or is newer
                if (!fs::exists(dstPath) || 
                    fs::last_write_time(entry) > fs::last_write_time(dstPath)) {
                    
                    fs::copy_file(entry.path(), dstPath,
                                  fs::copy_options::overwrite_existing);
                    std::cout << "Synced: " << relativePath << std::endl;
                }
            }
        }
        
    } catch (const fs::filesystem_error& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }
}

int main() {
    syncDirectories("source", "destination");
    return 0;
}

5. Common Issues

Issue 1: Overwrite Error

Here is detailed implementation code using C++. Import necessary modules, perform work efficiently through async processing, ensure stability through error handling. Understand the role of each part while examining the code.

#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

int main() {
    // ❌ Error if already exists
    try {
        fs::copy_file("src.txt", "existing.txt");
    } catch (const fs::filesystem_error& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        // filesystem error: cannot copy file: File exists
    }
    
    // ✅ Specify option
    fs::copy_file("src.txt", "existing.txt",
                  fs::copy_options::overwrite_existing);
    
    return 0;
}

Solution: Explicitly specify copy_options.

Issue 2: Directory Delete Failure

Below is an implementation example using C++. Perform work efficiently through async processing, ensure stability through error handling. Understand the role of each part while examining the code.

// ❌ Non-empty directory
try {
    fs::remove("non_empty_dir");  // Fails!
} catch (const fs::filesystem_error& e) {
    std::cerr << e.what() << std::endl;
    // Directory not empty
}

// ✅ Recursive delete
int removed = fs::remove_all("non_empty_dir");
std::cout << removed << " items deleted" << std::endl;

Solution: Use remove_all() for non-empty directories.

Issue 3: Move vs Copy

Below is an implementation example using C++. Perform work efficiently through async processing, ensure stability through error handling. Understand the role of each part while examining the code.

// Move (fast, atomic)
try {
    fs::rename("old.txt", "new.txt");
    // Only works within same filesystem
} catch (const fs::filesystem_error& e) {
    // Fails if different filesystem
    std::cerr << "Move failed: " << e.what() << std::endl;
}

// Copy + delete (slow, non-atomic)
fs::copy_file("src.txt", "dst.txt");
fs::remove("src.txt");
// Both files may exist if fails in middle

Solution: Use rename() within same filesystem, copy() + remove() across filesystems.


Master C++17 file operations! 🚀