Operações de Arquivos Windows - Exemplos C++

Exemplos abrangentes de operações de arquivo em C++ para plataforma Windows incluindo E/S de texto, cópia de arquivos e travessia de diretórios

💻 Operações de Leitura e Escrita de Arquivos de Texto cpp

🟢 simple ⭐⭐

Operações de arquivo de texto básicas e avançadas usando fluxos de arquivo C++ e APIs do Windows

⏱️ 20 min 🏷️ cpp, file, io, windows
Prerequisites: Basic C++, File streams, STL containers
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
#include <filesystem>
#include <windows.h>
#include <codecvt>
#include <locale>

namespace fs = std::filesystem;

// 1. Basic text file writing
void WriteSimpleText()
{
    std::cout << "=== Basic Text File Writing ===" << std::endl;

    std::string filename = "simple.txt";
    std::string content = "Hello, Windows! This is a simple text file written in C++.\n";
    content += "This file contains multiple lines of text.\n";
    content += "C++ file operations are powerful and flexible.\n";

    std::ofstream outFile(filename);
    if (outFile.is_open())
    {
        outFile << content;
        outFile.close();
        std::cout << "Successfully wrote to " << filename << std::endl;
    }
    else
    {
        std::cerr << "Error: Unable to open " << filename << " for writing" << std::endl;
    }
}

// 2. Writing with different character encodings
void WriteWithEncoding()
{
    std::cout << "\n=== Writing with UTF-8 Encoding ===" << std::endl;

    std::string filename = "utf8_text.txt";
    std::wstring content = L"Unicode text: 你好世界 🌍\n";
    content += L"Special characters: é ñ ü ß\n";
    content += L"Emojis: 😀 🎉 🚀\n";

    // Convert wide string to UTF-8
    std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
    std::string utf8Content = converter.to_bytes(content);

    std::ofstream outFile(filename, std::ios::binary);
    if (outFile.is_open())
    {
        outFile.write(utf8Content.c_str(), utf8Content.length());
        outFile.close();
        std::cout << "Successfully wrote UTF-8 text to " << filename << std::endl;
    }
    else
    {
        std::cerr << "Error: Unable to open " << filename << " for writing" << std::endl;
    }
}

// 3. Appending to files
void AppendToFile()
{
    std::cout << "\n=== Appending to Files ===" << std::endl;

    std::string filename = "append_log.txt";

    // Create initial file
    std::ofstream outFile(filename);
    if (outFile.is_open())
    {
        outFile << "Log started at: " << GetCurrentTimeString() << std::endl;
        outFile.close();
        std::cout << "Created initial log file: " << filename << std::endl;
    }

    // Append multiple entries
    for (int i = 1; i <= 3; i++)
    {
        std::ofstream appendFile(filename, std::ios::app);
        if (appendFile.is_open())
        {
            appendFile << "Log entry " << i << " at: " << GetCurrentTimeString() << std::endl;
            appendFile.close();
        }
    }

    std::cout << "Appended log entries to " << filename << std::endl;
}

// 4. Reading entire file
void ReadEntireFile()
{
    std::cout << "\n=== Reading Entire File ===" << std::endl;

    std::string filename = "simple.txt";

    if (!fs::exists(filename))
    {
        std::cerr << "Error: File " << filename << " does not exist" << std::endl;
        return;
    }

    std::ifstream inFile(filename);
    if (inFile.is_open())
    {
        std::stringstream buffer;
        buffer << inFile.rdbuf();
        std::string content = buffer.str();
        inFile.close();

        std::cout << "File content (" << content.length() << " characters):" << std::endl;
        std::cout << "---" << std::endl;
        std::cout << content;
        std::cout << "---" << std::endl;
    }
    else
    {
        std::cerr << "Error: Unable to open " << filename << " for reading" << std::endl;
    }
}

// 5. Reading file line by line
void ReadFileByLines()
{
    std::cout << "\n=== Reading File Line by Line ===" << std::endl;

    std::string filename = "append_log.txt";

    if (!fs::exists(filename))
    {
        std::cerr << "Error: File " << filename << " does not exist" << std::endl;
        return;
    }

    std::ifstream inFile(filename);
    if (inFile.is_open())
    {
        std::string line;
        int lineNumber = 0;

        std::cout << "Reading " << filename << " line by line:" << std::endl;
        while (std::getline(inFile, line))
        {
            lineNumber++;
            std::cout << "Line " << lineNumber << ": " << line << std::endl;
        }

        inFile.close();
        std::cout << "Total lines read: " << lineNumber << std::endl;
    }
    else
    {
        std::cerr << "Error: Unable to open " << filename << " for reading" << std::endl;
    }
}

// 6. Reading with error handling
void ReadWithErrorHandling()
{
    std::cout << "\n=== Reading with Error Handling ===" << std::endl;

    std::string filename = "nonexistent.txt";

    try
    {
        std::ifstream inFile(filename);
        if (!inFile)
        {
            throw std::runtime_error("Failed to open file: " + filename);
        }

        inFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);

        std::string content;
        inFile >> content;

        std::cout << "Successfully read: " << content << std::endl;
        inFile.close();
    }
    catch (const std::exception& e)
    {
        std::cerr << "Error reading file: " << e.what() << std::endl;
    }
}

// 7. Reading UTF-8 encoded files
void ReadUtf8File()
{
    std::cout << "\n=== Reading UTF-8 File ===" << std::endl;

    std::string filename = "utf8_text.txt";

    if (!fs::exists(filename))
    {
        std::cerr << "Error: File " << filename << " does not exist" << std::endl;
        return;
    }

    // Read as binary
    std::ifstream inFile(filename, std::ios::binary);
    if (inFile.is_open())
    {
        // Get file size
        inFile.seekg(0, std::ios::end);
        size_t fileSize = inFile.tellg();
        inFile.seekg(0, std::ios::beg);

        // Read file content
        std::string content(fileSize, '\0');
        inFile.read(&content[0], fileSize);
        inFile.close();

        // Convert UTF-8 to wide string for display
        std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
        std::wstring wideContent;

        try
        {
            wideContent = converter.from_bytes(content);
            std::wcout << L"UTF-8 content: " << wideContent << std::endl;
        }
        catch (const std::exception& e)
        {
            std::cout << "Error converting UTF-8: " << e.what() << std::endl;
            std::cout << "Raw UTF-8 bytes: " << content << std::endl;
        }
    }
    else
    {
        std::cerr << "Error: Unable to open " << filename << " for reading" << std::endl;
    }
}

// 8. File seeking and random access
void DemonstrateFileSeeking()
{
    std::cout << "\n=== File Seeking and Random Access ===" << std::endl;

    std::string filename = "random_access.txt";

    // Create a file with structured data
    {
        std::ofstream outFile(filename);
        if (outFile.is_open())
        {
            outFile << "Line 1: First line\n";
            outFile << "Line 2: Second line\n";
            outFile << "Line 3: Third line\n";
            outFile << "Line 4: Fourth line\n";
            outFile << "Line 5: Fifth line\n";
            outFile.close();
        }
    }

    // Demonstrate seeking
    std::ifstream inFile(filename);
    if (inFile.is_open())
    {
        // Get file size
        inFile.seekg(0, std::ios::end);
        long fileSize = inFile.tellg();
        std::cout << "File size: " << fileSize << " bytes" << std::endl;

        // Seek to middle
        long middlePos = fileSize / 2;
        inFile.seekg(middlePos);

        std::string content;
        std::getline(inFile, content);
        std::cout << "Content from middle position: " << content << std::endl;

        // Seek back to beginning
        inFile.seekg(0, std::ios::beg);
        std::getline(inFile, content);
        std::cout << "First line: " << content << std::endl;

        inFile.close();
    }
}

// 9. Binary file operations
void BinaryFileOperations()
{
    std::cout << "\n=== Binary File Operations ===" << std::endl;

    std::string filename = "data.bin";

    // Write binary data
    {
        std::ofstream outFile(filename, std::ios::binary);
        if (outFile.is_open())
        {
            int intValue = 42;
            double doubleValue = 3.14159;
            std::string stringValue = "Binary Data";

            outFile.write(reinterpret_cast<const char*>(&intValue), sizeof(intValue));
            outFile.write(reinterpret_cast<const char*>(&doubleValue), sizeof(doubleValue));

            // Write string with length prefix
            size_t stringLength = stringValue.length();
            outFile.write(reinterpret_cast<const char*>(&stringLength), sizeof(stringLength));
            outFile.write(stringValue.c_str(), stringLength);

            outFile.close();
            std::cout << "Wrote binary data to " << filename << std::endl;
        }
    }

    // Read binary data
    {
        std::ifstream inFile(filename, std::ios::binary);
        if (inFile.is_open())
        {
            int intValue;
            double doubleValue;
            std::string stringValue;

            inFile.read(reinterpret_cast<char*>(&intValue), sizeof(intValue));
            inFile.read(reinterpret_cast<char*>(&doubleValue), sizeof(doubleValue));

            size_t stringLength;
            inFile.read(reinterpret_cast<char*>(&stringLength), sizeof(stringLength));
            stringValue.resize(stringLength);
            inFile.read(&stringValue[0], stringLength);

            std::cout << "Read binary data:" << std::endl;
            std::cout << "  Integer: " << intValue << std::endl;
            std::cout << "  Double: " << doubleValue << std::endl;
            std::cout << "  String: " << stringValue << std::endl;

            inFile.close();
        }
    }
}

// 10. High-performance file reading
void HighPerformanceFileReading()
{
    std::cout << "\n=== High-Performance File Reading ===" << std::endl;

    std::string filename = "large_file.txt";

    // Create a large file
    {
        std::ofstream outFile(filename);
        if (outFile.is_open())
        {
            for (int i = 1; i <= 1000; i++)
            {
                outFile << "Line " << i << ": This is a test line with some content for demonstration purposes. ";
                outFile << "The line number is " << i << ". ";
                outFile << "Random data: " << (rand() % 1000) << "\n";
            }
            outFile.close();
            std::cout << "Created large file with 1000 lines" << std::endl;
        }
    }

    // Read with buffering
    {
        auto start = std::chrono::high_resolution_clock::now();

        std::ifstream inFile(filename);
        inFile.rdbuf()->pubsetbuf(nullptr, 0); // No buffering for comparison

        std::string content;
        content.reserve(100000); // Pre-allocate memory

        char buffer[8192];
        while (inFile.read(buffer, sizeof(buffer)))
        {
            content.append(buffer, sizeof(buffer));
        }
        content.append(buffer, inFile.gcount());

        auto end = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

        std::cout << "Read " << content.length() << " characters in " << duration.count() << " ms" << std::endl;

        inFile.close();
    }
}

// Helper function to get current time string
std::string GetCurrentTimeString()
{
    auto now = std::chrono::system_clock::now();
    auto time_t = std::chrono::system_clock::to_time_t(now);
    auto tm = *std::localtime(&time_t);

    std::ostringstream oss;
    oss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S");
    return oss.str();
}

// Cleanup function
void CleanupFiles()
{
    std::cout << "\n=== Cleaning Up Files ===" << std::endl;

    std::vector<std::string> filesToCleanup = {
        "simple.txt", "utf8_text.txt", "append_log.txt",
        "random_access.txt", "data.bin", "large_file.txt"
    };

    for (const auto& file : filesToCleanup)
    {
        try
        {
            if (fs::exists(file))
            {
                fs::remove(file);
                std::cout << "Deleted: " << file << std::endl;
            }
        }
        catch (const std::exception& e)
        {
            std::cerr << "Error deleting " << file << ": " << e.what() << std::endl;
        }
    }
}

int main()
{
    std::cout << "=== C++ Windows File Operations Demo ===" << std::endl;
    std::cout << "Demonstrating various file operations using C++\n" << std::endl;

    try
    {
        // Basic file operations
        WriteSimpleText();
        ReadEntireFile();

        // Encoding operations
        WriteWithEncoding();
        ReadUtf8File();

        // Appending operations
        AppendToFile();
        ReadFileByLines();

        // Error handling
        ReadWithErrorHandling();

        // Advanced operations
        DemonstrateFileSeeking();
        BinaryFileOperations();
        HighPerformanceFileReading();

        std::cout << "\nAll file operations completed successfully!" << std::endl;
    }
    catch (const std::exception& e)
    {
        std::cerr << "Unexpected error: " << e.what() << std::endl;
        return 1;
    }

    // Clean up
    CleanupFiles();

    return 0;
}

💻 Operações de Cópia e Movimento de Arquivos cpp

🟡 intermediate ⭐⭐

Operações de cópia, movimento e lote de arquivos com rastreamento de progresso e tratamento de erros

⏱️ 25 min 🏷️ cpp, file, copy, windows
Prerequisites: C++ file streams, STL filesystem, Windows API basics
#include <iostream>
#include <fstream>
#include <filesystem>
#include <vector>
#include <string>
#include <chrono>
#include <iomanip>
#include <windows.h>
#include <shlobj.h>

namespace fs = std::filesystem;

// Progress callback type
using ProgressCallback = std::function<void(long long, long long)>;

// 1. Simple file copy
bool SimpleFileCopy(const std::string& sourcePath, const std::string& destPath)
{
    std::cout << "=== Simple File Copy ===" << std::endl;
    std::cout << "Source: " << sourcePath << std::endl;
    std::cout << "Destination: " << destPath << std::endl;

    try
    {
        if (!fs::exists(sourcePath))
        {
            std::cerr << "Error: Source file does not exist" << std::endl;
            return false;
        }

        // Create destination directory if it doesn't exist
        fs::path destFilePath(destPath);
        fs::create_directories(destFilePath.parent_path());

        // Check if destination already exists
        if (fs::exists(destPath))
        {
            std::cout << "Warning: Destination file already exists, overwriting..." << std::endl;
            fs::remove(destPath);
        }

        // Copy file
        fs::copy_file(sourcePath, destPath, fs::copy_options::overwrite_existing);

        // Verify copy
        if (fs::exists(destPath))
        {
            auto sourceSize = fs::file_size(sourcePath);
            auto destSize = fs::file_size(destPath);

            if (sourceSize == destSize)
            {
                std::cout << "File copied successfully! Size: " << sourceSize << " bytes" << std::endl;
                return true;
            }
            else
            {
                std::cerr << "Error: File size mismatch after copy" << std::endl;
                return false;
            }
        }
        else
        {
            std::cerr << "Error: Destination file was not created" << std::endl;
            return false;
        }
    }
    catch (const std::exception& e)
    {
        std::cerr << "Error copying file: " << e.what() << std::endl;
        return false;
    }
}

// 2. File copy with progress tracking
bool CopyFileWithProgress(const std::string& sourcePath, const std::string& destPath, ProgressCallback progressCallback = nullptr)
{
    std::cout << "\n=== File Copy with Progress ===" << std::endl;

    try
    {
        if (!fs::exists(sourcePath))
        {
            std::cerr << "Error: Source file does not exist" << std::endl;
            return false;
        }

        long long fileSize = fs::file_size(sourcePath);
        std::cout << "Copying file: " << fileSize << " bytes" << std::endl;

        // Create destination directory
        fs::path destFilePath(destPath);
        fs::create_directories(destFilePath.parent_path());

        // Open source and destination files
        std::ifstream source(sourcePath, std::ios::binary);
        std::ofstream dest(destPath, std::ios::binary);

        if (!source.is_open() || !dest.is_open())
        {
            std::cerr << "Error: Unable to open source or destination file" << std::endl;
            return false;
        }

        // Copy with buffer and progress tracking
        const int BUFFER_SIZE = 64 * 1024; // 64KB buffer
        std::vector<char> buffer(BUFFER_SIZE);
        long long totalCopied = 0;

        auto startTime = std::chrono::high_resolution_clock::now();

        while (source)
        {
            source.read(buffer.data(), BUFFER_SIZE);
            std::streamsize bytesRead = source.gcount();

            if (bytesRead > 0)
            {
                dest.write(buffer.data(), bytesRead);
                totalCopied += bytesRead;

                // Report progress
                if (progressCallback)
                {
                    progressCallback(totalCopied, fileSize);
                }

                // Show progress in console
                double progress = (double)totalCopied / fileSize * 100.0;
                std::cout << "\rProgress: " << std::fixed << std::setprecision(1) << progress << "% ("
                          << totalCopied << "/" << fileSize << " bytes)";
                std::cout.flush();
            }
        }

        auto endTime = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);

        source.close();
        dest.close();

        std::cout << "\nCopy completed in " << duration.count() << " ms" << std::endl;

        // Calculate speed
        double speedMBps = (totalCopied / (1024.0 * 1024.0)) / (duration.count() / 1000.0);
        std::cout << "Speed: " << std::fixed << std::setprecision(2) << speedMBps << " MB/s" << std::endl;

        return true;
    }
    catch (const std::exception& e)
    {
        std::cerr << "\nError during copy: " << e.what() << std::endl;
        return false;
    }
}

// 3. Safe file move with rollback
bool SafeFileMove(const std::string& sourcePath, const std::string& destPath)
{
    std::cout << "\n=== Safe File Move with Rollback ===" << std::endl;

    std::string tempPath = destPath + ".tmp";

    try
    {
        if (!fs::exists(sourcePath))
        {
            std::cerr << "Error: Source file does not exist" << std::endl;
            return false;
        }

        if (fs::exists(destPath))
        {
            std::cerr << "Error: Destination file already exists" << std::endl;
            return false;
        }

        // Create destination directory
        fs::path destFilePath(destPath);
        fs::create_directories(destFilePath.parent_path());

        // Step 1: Copy to temporary location
        std::cout << "Step 1: Copying to temporary location..." << std::endl;
        if (!CopyFileWithProgress(sourcePath, tempPath))
        {
            return false;
        }

        // Step 2: Verify temporary copy
        std::cout << "Step 2: Verifying temporary copy..." << std::endl;
        if (!VerifyFileCopy(sourcePath, tempPath))
        {
            fs::remove(tempPath);
            std::cerr << "Error: Temporary copy verification failed" << std::endl;
            return false;
        }

        // Step 3: Move to final destination
        std::cout << "Step 3: Moving to final destination..." << std::endl;
        fs::rename(tempPath, destPath);

        // Step 4: Remove original
        std::cout << "Step 4: Removing original file..." << std::endl;
        fs::remove(sourcePath);

        std::cout << "File move completed successfully!" << std::endl;
        return true;
    }
    catch (const std::exception& e)
    {
        std::cerr << "Error during move: " << e.what() << std::endl;

        // Rollback: remove temporary file if it exists
        if (fs::exists(tempPath))
        {
            fs::remove(tempPath);
            std::cout << "Rollback: Removed temporary file" << std::endl;
        }

        return false;
    }
}

// 4. Verify file copy integrity
bool VerifyFileCopy(const std::string& sourcePath, const std::string& destPath)
{
    try
    {
        if (!fs::exists(sourcePath) || !fs::exists(destPath))
        {
            return false;
        }

        auto sourceSize = fs::file_size(sourcePath);
        auto destSize = fs::file_size(destPath);

        if (sourceSize != destSize)
        {
            std::cout << "Size mismatch: source=" << sourceSize << ", dest=" << destSize << std::endl;
            return false;
        }

        // For small files, verify content
        if (sourceSize < 1024 * 1024) // < 1MB
        {
            std::ifstream source(sourcePath, std::ios::binary);
            std::ifstream dest(destPath, std::ios::binary);

            if (!source.is_open() || !dest.is_open())
            {
                return false;
            }

            const int BUFFER_SIZE = 4096;
            std::vector<char> sourceBuffer(BUFFER_SIZE);
            std::vector<char> destBuffer(BUFFER_SIZE);

            while (source && dest)
            {
                source.read(sourceBuffer.data(), BUFFER_SIZE);
                dest.read(destBuffer.data(), BUFFER_SIZE);

                if (source.gcount() != dest.gcount())
                {
                    return false;
                }

                if (memcmp(sourceBuffer.data(), destBuffer.data(), source.gcount()) != 0)
                {
                    std::cout << "Content mismatch detected" << std::endl;
                    return false;
                }
            }
        }

        return true;
    }
    catch (const std::exception& e)
    {
        std::cerr << "Error verifying file copy: " << e.what() << std::endl;
        return false;
    }
}

// 5. Batch file operations
void BatchFileOperations()
{
    std::cout << "\n=== Batch File Operations ===" << std::endl;

    // Create test files
    std::string sourceDir = "batch_source";
    std::string destDir = "batch_dest";

    fs::create_directories(sourceDir);
    fs::create_directories(destDir);

    std::cout << "Creating test files..." << std::endl;
    for (int i = 1; i <= 5; i++)
    {
        std::string filename = sourceDir + "/file" + std::to_string(i) + ".txt";
        std::ofstream outFile(filename);
        outFile << "This is test file " << i << std::endl;
        outFile << "Content for batch operations demonstration." << std::endl;
        for (int j = 1; j <= 10; j++)
        {
            outFile << "Line " << j << " of file " << i << std::endl;
        }
        outFile.close();
    }

    // Batch copy with progress tracking
    std::cout << "\nStarting batch copy..." << std::endl;
    int copiedFiles = 0;
    int totalFiles = 0;

    // Count total files
    for (const auto& entry : fs::directory_iterator(sourceDir))
    {
        if (entry.is_regular_file())
        {
            totalFiles++;
        }
    }

    // Copy files with progress
    int fileIndex = 0;
    for (const auto& entry : fs::directory_iterator(sourceDir))
    {
        if (entry.is_regular_file())
        {
            fileIndex++;
            std::string sourcePath = entry.path().string();
            std::string destPath = destDir + "/" + entry.path().filename().string();

            std::cout << "\nCopying file " << fileIndex << "/" << totalFiles << ": " << entry.path().filename().string() << std::endl;

            if (SimpleFileCopy(sourcePath, destPath))
            {
                copiedFiles++;
                std::cout << "✓ Successfully copied" << std::endl;
            }
            else
            {
                std::cout << "✗ Failed to copy" << std::endl;
            }
        }
    }

    std::cout << "\nBatch copy completed: " << copiedFiles << "/" << totalFiles << " files copied" << std::endl;
}

// 6. Directory copy (recursive)
bool CopyDirectory(const std::string& sourceDir, const std::string& destDir, ProgressCallback progressCallback = nullptr)
{
    std::cout << "\n=== Recursive Directory Copy ===" << std::endl;

    try
    {
        if (!fs::exists(sourceDir))
        {
            std::cerr << "Error: Source directory does not exist" << std::endl;
            return false;
        }

        // Create destination directory
        fs::create_directories(destDir);

        long long totalFiles = 0;
        long long copiedFiles = 0;

        // Count total files first
        for (const auto& entry : fs::recursive_directory_iterator(sourceDir))
        {
            if (entry.is_regular_file())
            {
                totalFiles++;
            }
        }

        std::cout << "Found " << totalFiles << " files to copy" << std::endl;

        // Copy directory recursively
        for (const auto& entry : fs::recursive_directory_iterator(sourceDir))
        {
            if (entry.is_regular_file())
            {
                std::string relativePath = fs::relative(entry.path(), sourceDir).string();
                std::string destPath = destDir + "/" + relativePath;

                std::cout << "Copying: " << relativePath << std::endl;

                if (SimpleFileCopy(entry.path().string(), destPath))
                {
                    copiedFiles++;

                    // Report progress
                    if (progressCallback)
                    {
                        progressCallback(copiedFiles, totalFiles);
                    }
                }
            }
            else if (entry.is_directory())
            {
                // Create corresponding directory structure
                std::string relativePath = fs::relative(entry.path(), sourceDir).string();
                std::string destPath = destDir + "/" + relativePath;
                fs::create_directories(destPath);
            }
        }

        std::cout << "Directory copy completed: " << copiedFiles << " files copied" << std::endl;
        return true;
    }
    catch (const std::exception& e)
    {
        std::cerr << "Error copying directory: " << e.what() << std::endl;
        return false;
    }
}

// 7. Windows-specific file operations using Win32 API
void WindowsFileOperations()
{
    std::cout << "\n=== Windows-Specific File Operations ===" << std::endl;

    std::string sourceFile = "win32_test.txt";
    std::string destFile = "win32_copy.txt";

    // Create test file
    {
        std::ofstream outFile(sourceFile);
        outFile << "This file will be copied using Win32 API" << std::endl;
        outFile << "Content for Win32 API demonstration" << std::endl;
    }

    // Use CopyFile Win32 API
    BOOL result = CopyFileA(sourceFile.c_str(), destFile.c_str(), FALSE);

    if (result)
    {
        std::cout << "Win32 CopyFile succeeded" << std::endl;

        // Get file attributes
        DWORD attributes = GetFileAttributesA(destFile.c_str());
        if (attributes != INVALID_FILE_ATTRIBUTES)
        {
            std::cout << "File attributes: " << std::hex << attributes << std::dec << std::endl;
            if (attributes & FILE_ATTRIBUTE_READONLY)
                std::cout << "  - Read-only" << std::endl;
            if (attributes & FILE_ATTRIBUTE_HIDDEN)
                std::cout << "  - Hidden" << std::endl;
            if (attributes & FILE_ATTRIBUTE_ARCHIVE)
                std::cout << "  - Archive" << std::endl;
        }
    }
    else
    {
        DWORD error = GetLastError();
        std::cerr << "Win32 CopyFile failed with error: " << error << std::endl;
    }
}

// 8. File backup with timestamp
bool CreateBackupWithTimestamp(const std::string& filePath)
{
    std::cout << "\n=== Creating Backup with Timestamp ===" << std::endl;

    try
    {
        if (!fs::exists(filePath))
        {
            std::cerr << "Error: Source file does not exist" << std::endl;
            return false;
        }

        // Create backup filename with timestamp
        auto now = std::chrono::system_clock::now();
        auto time_t = std::chrono::system_clock::to_time_t(now);
        auto tm = *std::localtime(&time_t);

        std::ostringstream oss;
        oss << std::put_time(&tm, "%Y%m%d_%H%M%S");

        fs::path sourcePath(filePath);
        std::string backupPath = sourcePath.parent_path() /
                               (sourcePath.stem().string() + "_backup_" + oss.str() +
                                sourcePath.extension().string());

        std::cout << "Creating backup: " << backupPath << std::endl;

        if (SimpleFileCopy(filePath, backupPath))
        {
            std::cout << "Backup created successfully" << std::endl;
            return true;
        }
        else
        {
            std::cerr << "Failed to create backup" << std::endl;
            return false;
        }
    }
    catch (const std::exception& e)
    {
        std::cerr << "Error creating backup: " << e.what() << std::endl;
        return false;
    }
}

// Cleanup function
void CleanupTestFiles()
{
    std::cout << "\n=== Cleaning Up Test Files ===" << std::endl;

    std::vector<std::string> filesToRemove = {
        "simple.txt", "copy.txt", "move.txt", "win32_test.txt", "win32_copy.txt"
    };

    std::vector<std::string> dirsToRemove = {
        "batch_source", "batch_dest", "recursive_source", "recursive_dest"
    };

    for (const auto& file : filesToRemove)
    {
        try
        {
            if (fs::exists(file))
            {
                fs::remove(file);
                std::cout << "Removed file: " << file << std::endl;
            }
        }
        catch (const std::exception& e)
        {
            std::cerr << "Error removing " << file << ": " << e.what() << std::endl;
        }
    }

    for (const auto& dir : dirsToRemove)
    {
        try
        {
            if (fs::exists(dir))
            {
                fs::remove_all(dir);
                std::cout << "Removed directory: " << dir << std::endl;
            }
        }
        catch (const std::exception& e)
        {
            std::cerr << "Error removing " << dir << ": " << e.what() << std::endl;
        }
    }
}

// Progress callback function
void ShowProgress(long long current, long long total)
{
    double progress = (double)current / total * 100.0;
    std::cout << "\rProgress: " << std::fixed << std::setprecision(1) << progress << "%";
    std::cout.flush();
}

int main()
{
    std::cout << "=== C++ Windows File Copy/Move Operations ===" << std::endl;
    std::cout << "Demonstrating various file copy and move operations\n" << std::endl;

    try
    {
        // Create a test file first
        std::string testFile = "simple.txt";
        {
            std::ofstream outFile(testFile);
            outFile << "This is a test file for copy and move operations.\n";
            outFile << "It contains multiple lines of text.\n";
            outFile << "C++ file operations are efficient and reliable.\n";
            outFile.close();
        }

        // Simple copy
        SimpleFileCopy(testFile, "copy.txt");

        // Copy with progress
        CopyFileWithProgress(testFile, "large_copy.txt", ShowProgress);

        // Safe move
        SimpleFileCopy(testFile, "move.txt");
        SafeFileMove("move.txt", "moved_file.txt");

        // Batch operations
        BatchFileOperations();

        // Directory copy
        fs::create_directories("recursive_source/subdir");
        {
            std::ofstream outFile("recursive_source/file1.txt");
            outFile << "File in source directory";
            outFile.close();
        }
        {
            std::ofstream outFile("recursive_source/subdir/file2.txt");
            outFile << "File in subdirectory";
            outFile.close();
        }
        CopyDirectory("recursive_source", "recursive_dest");

        // Windows-specific operations
        WindowsFileOperations();

        // Backup with timestamp
        CreateBackupWithTimestamp(testFile);

        std::cout << "\nAll file copy/move operations completed successfully!" << std::endl;
    }
    catch (const std::exception& e)
    {
        std::cerr << "Unexpected error: " << e.what() << std::endl;
        return 1;
    }

    // Clean up
    CleanupTestFiles();

    return 0;
}

💻 Travessia de Diretórios e Listagem de Arquivos cpp

🟡 intermediate ⭐⭐⭐

Operações completas de diretórios incluindo travessia, busca de arquivos e análise estatística

⏱️ 30 min 🏷️ cpp, directory, filesystem, windows
Prerequisites: C++17 filesystem, STL containers, Regular expressions
#include <iostream>
#include <filesystem>
#include <vector>
#include <string>
#include <algorithm>
#include <iomanip>
#include <chrono>
#include <regex>
#include <windows.h>
#include <lmcons.h>

namespace fs = std::filesystem;

// File information structure
struct FileInfo {
    std::string name;
    std::string path;
    long long size;
    std::string extension;
    std::chrono::system_clock::time_point lastModified;
    bool isDirectory;

    std::string formatSize() const {
        const char* units[] = {"B", "KB", "MB", "GB", "TB"};
        double size = static_cast<double>(this->size);
        int unitIndex = 0;

        while (size >= 1024.0 && unitIndex < 4) {
            size /= 1024.0;
            unitIndex++;
        }

        std::ostringstream oss;
        oss << std::fixed << std::setprecision(2) << size << " " << units[unitIndex];
        return oss.str();
    }
};

// 1. Basic directory listing
void ListDirectoryContents(const std::string& directoryPath)
{
    std::cout << "=== Basic Directory Listing ===" << std::endl;
    std::cout << "Directory: " << directoryPath << std::endl;

    try {
        if (!fs::exists(directoryPath)) {
            std::cerr << "Error: Directory does not exist" << std::endl;
            return;
        }

        if (!fs::is_directory(directoryPath)) {
            std::cerr << "Error: Path is not a directory" << std::endl;
            return;
        }

        std::vector<FileInfo> files;
        std::vector<FileInfo> directories;

        for (const auto& entry : fs::directory_iterator(directoryPath)) {
            FileInfo info;
            info.name = entry.path().filename().string();
            info.path = entry.path().string();
            info.isDirectory = entry.is_directory();

            if (entry.is_regular_file()) {
                info.size = entry.file_size();
                info.extension = entry.path().extension().string();
                info.lastModified = entry.last_write_time();
                files.push_back(info);
            } else if (entry.is_directory()) {
                info.size = 0;
                info.extension = "";
                info.lastModified = entry.last_write_time();
                directories.push_back(info);
            }
        }

        // Sort alphabetically
        std::sort(directories.begin(), directories.end(),
                 [](const FileInfo& a, const FileInfo& b) { return a.name < b.name; });
        std::sort(files.begin(), files.end(),
                 [](const FileInfo& a, const FileInfo& b) { return a.name < b.name; });

        // Display directories
        std::cout << "\nDirectories (" << directories.size() << "):" << std::endl;
        for (const auto& dir : directories) {
            std::cout << "  📁 " << dir.name << "/" << std::endl;
        }

        // Display files
        std::cout << "\nFiles (" << files.size() << "):" << std::endl;
        for (const auto& file : files) {
            std::cout << "  📄 " << std::left << std::setw(30) << file.name
                      << std::setw(12) << file.formatSize()
                      << "  " << file.extension << std::endl;
        }

    } catch (const std::exception& e) {
        std::cerr << "Error listing directory: " << e.what() << std::endl;
    }
}

// 2. Recursive directory traversal
void RecursiveDirectoryTraversal(const std::string& rootPath, int maxDepth = 3, int currentDepth = 0)
{
    std::cout << "\n=== Recursive Directory Traversal ===" << std::endl;
    std::cout << "Root: " << rootPath << " (Max depth: " << maxDepth << ")" << std::endl;

    try {
        if (currentDepth >= maxDepth) {
            std::cout << "  (Max depth reached)" << std::endl;
            return;
        }

        std::string indent(currentDepth * 2, ' ');

        if (!fs::exists(rootPath) || !fs::is_directory(rootPath)) {
            std::cerr << indent << "Error: Invalid directory path" << std::endl;
            return;
        }

        std::cout << indent << "📁 " << fs::path(rootPath).filename().string() << "/" << std::endl;

        for (const auto& entry : fs::directory_iterator(rootPath)) {
            if (entry.is_directory()) {
                // Recursively traverse subdirectory
                RecursiveDirectoryTraversal(entry.path().string(), maxDepth, currentDepth + 1);
            } else if (entry.is_regular_file()) {
                std::cout << indent << "  📄 " << entry.path().filename().string()
                          << " (" << entry.file_size() << " bytes)" << std::endl;
            }
        }

    } catch (const std::exception& e) {
        std::cerr << "Error during recursive traversal: " << e.what() << std::endl;
    }
}

// 3. Calculate directory size
long long CalculateDirectorySize(const std::string& directoryPath)
{
    std::cout << "\n=== Calculating Directory Size ===" << std::endl;

    long long totalSize = 0;
    int fileCount = 0;
    int dirCount = 0;

    try {
        for (const auto& entry : fs::recursive_directory_iterator(directoryPath)) {
            if (entry.is_regular_file()) {
                totalSize += entry.file_size();
                fileCount++;
            } else if (entry.is_directory()) {
                dirCount++;
            }
        }

        std::cout << "Directory: " << directoryPath << std::endl;
        std::cout << "Total size: " << totalSize << " bytes ("
                  << formatBytes(totalSize) << ")" << std::endl;
        std::cout << "Files: " << fileCount << std::endl;
        std::cout << "Subdirectories: " << dirCount << std::endl;

    } catch (const std::exception& e) {
        std::cerr << "Error calculating directory size: " << e.what() << std::endl;
    }

    return totalSize;
}

// 4. Search files by pattern
std::vector<FileInfo> SearchFilesByPattern(const std::string& directoryPath, const std::string& pattern)
{
    std::cout << "\n=== Search Files by Pattern ===" << std::endl;
    std::cout << "Directory: " << directoryPath << std::endl;
    std::cout << "Pattern: " << pattern << std::endl;

    std::vector<FileInfo> results;
    std::regex regexPattern(pattern, std::regex_constants::icase);

    try {
        for (const auto& entry : fs::recursive_directory_iterator(directoryPath)) {
            if (entry.is_regular_file()) {
                std::string filename = entry.path().filename().string();

                if (std::regex_search(filename, regexPattern)) {
                    FileInfo info;
                    info.name = filename;
                    info.path = entry.path().string();
                    info.size = entry.file_size();
                    info.extension = entry.path().extension().string();
                    info.lastModified = entry.last_write_time();
                    info.isDirectory = false;

                    results.push_back(info);
                }
            }
        }

        // Sort by size (largest first)
        std::sort(results.begin(), results.end(),
                 [](const FileInfo& a, const FileInfo& b) { return a.size > b.size; });

        std::cout << "Found " << results.size() << " matching files:" << std::endl;
        for (const auto& file : results) {
            std::cout << "  " << file.name << " (" << file.formatSize() << ")" << std::endl;
        }

    } catch (const std::exception& e) {
        std::cerr << "Error searching files: " << e.what() << std::endl;
    }

    return results;
}

// 5. Find recently modified files
std::vector<FileInfo> FindRecentlyModifiedFiles(const std::string& directoryPath, int hoursAgo)
{
    std::cout << "\n=== Find Recently Modified Files ===" << std::endl;
    std::cout << "Directory: " << directoryPath << std::endl;
    std::cout << "Time window: Last " << hoursAgo << " hours" << std::endl;

    std::vector<FileInfo> recentFiles;
    auto cutoffTime = std::chrono::system_clock::now() - std::chrono::hours(hoursAgo);

    try {
        for (const auto& entry : fs::recursive_directory_iterator(directoryPath)) {
            if (entry.is_regular_file()) {
                auto fileTime = std::chrono::clock_cast<std::chrono::system_clock>(entry.last_write_time());

                if (fileTime > cutoffTime) {
                    FileInfo info;
                    info.name = entry.path().filename().string();
                    info.path = entry.path().string();
                    info.size = entry.file_size();
                    info.extension = entry.path().extension().string();
                    info.lastModified = entry.last_write_time();
                    info.isDirectory = false;

                    recentFiles.push_back(info);
                }
            }
        }

        // Sort by modification time (newest first)
        std::sort(recentFiles.begin(), recentFiles.end(),
                 [](const FileInfo& a, const FileInfo& b) { return a.lastModified > b.lastModified; });

        std::cout << "Found " << recentFiles.size() << " recently modified files:" << std::endl;
        for (const auto& file : recentFiles) {
            auto time_t = std::chrono::system_clock::to_time_t(file.lastModified);
            auto tm = *std::localtime(&time_t);

            std::cout << "  " << file.name << " - " << std::put_time(&tm, "%Y-%m-%d %H:%M:%S")
                      << " (" << file.formatSize() << ")" << std::endl;
        }

    } catch (const std::exception& e) {
        std::cerr << "Error finding recently modified files: " << e.what() << std::endl;
    }

    return recentFiles;
}

// 6. Find duplicate files by size and content
void FindDuplicateFiles(const std::string& directoryPath)
{
    std::cout << "\n=== Find Duplicate Files ===" << std::endl;
    std::cout << "Directory: " << directoryPath << std::endl;

    std::map<long long, std::vector<FileInfo>> filesBySize;

    try {
        // Group files by size
        for (const auto& entry : fs::recursive_directory_iterator(directoryPath)) {
            if (entry.is_regular_file()) {
                FileInfo info;
                info.name = entry.path().filename().string();
                info.path = entry.path().string();
                info.size = entry.file_size();
                info.extension = entry.path().extension().string();
                info.isDirectory = false;

                filesBySize[info.size].push_back(info);
            }
        }

        // Find potential duplicates (files with same size)
        int potentialDuplicateGroups = 0;
        int confirmedDuplicates = 0;

        for (const auto& [size, files] : filesBySize) {
            if (files.size() > 1) {
                potentialDuplicateGroups++;
                std::cout << "\nFiles with same size (" << files.size() << " files, "
                          << formatBytes(size) << "):" << std::endl;

                for (const auto& file : files) {
                    std::cout << "  " << file.path << std::endl;
                }

                // For demonstration, we'll just count them as duplicates
                // In a real implementation, you'd compare file hashes
                if (files.size() > 1) {
                    confirmedDuplicates += files.size() - 1;
                }
            }
        }

        std::cout << "\nSummary:" << std::endl;
        std::cout << "Potential duplicate groups: " << potentialDuplicateGroups << std::endl;
        std::cout << "Files that could be removed: " << confirmedDuplicates << std::endl;

    } catch (const std::exception& e) {
        std::cerr << "Error finding duplicate files: " << e.what() << std::endl;
    }
}

// 7. Directory statistics analysis
void AnalyzeDirectoryStatistics(const std::string& directoryPath)
{
    std::cout << "\n=== Directory Statistics Analysis ===" << std::endl;
    std::cout << "Analyzing: " << directoryPath << std::endl;

    try {
        std::map<std::string, int> extensionCounts;
        std::map<std::string, long long> extensionSizes;
        std::vector<long long> fileSizes;
        int totalFiles = 0;
        int totalDirectories = 0;
        long long totalSize = 0;

        // Collect statistics
        for (const auto& entry : fs::recursive_directory_iterator(directoryPath)) {
            if (entry.is_regular_file()) {
                totalFiles++;
                long long fileSize = entry.file_size();
                totalSize += fileSize;
                fileSizes.push_back(fileSize);

                std::string ext = entry.path().extension().string();
                if (ext.empty()) ext = "[no extension]";

                extensionCounts[ext]++;
                extensionSizes[ext] += fileSize;
            } else if (entry.is_directory()) {
                totalDirectories++;
            }
        }

        // Calculate statistics
        std::sort(fileSizes.begin(), fileSizes.end());

        long long medianSize = 0;
        if (!fileSizes.empty()) {
            size_t midIndex = fileSizes.size() / 2;
            medianSize = fileSizes[midIndex];
        }

        // Display results
        std::cout << "\nOverall Statistics:" << std::endl;
        std::cout << "  Total files: " << totalFiles << std::endl;
        std::cout << "  Total directories: " << totalDirectories << std::endl;
        std::cout << "  Total size: " << formatBytes(totalSize) << std::endl;

        if (!fileSizes.empty()) {
            std::cout << "  Smallest file: " << formatBytes(fileSizes[0]) << std::endl;
            std::cout << "  Largest file: " << formatBytes(fileSizes.back()) << std::endl;
            std::cout << "  Median file size: " << formatBytes(medianSize) << std::endl;

            if (totalFiles > 0) {
                std::cout << "  Average file size: " << formatBytes(totalSize / totalFiles) << std::endl;
            }
        }

        // Display file type statistics
        std::cout << "\nFile Types:" << std::endl;

        // Sort by size (largest first)
        std::vector<std::pair<std::string, long long>> sortedExtensions(
            extensionSizes.begin(), extensionSizes.end());
        std::sort(sortedExtensions.begin(), sortedExtensions.end(),
                 [](const auto& a, const auto& b) { return a.second > b.second; });

        for (const auto& [ext, size] : sortedExtensions) {
            int count = extensionCounts[ext];
            double percentage = totalFiles > 0 ? (double)count / totalFiles * 100.0 : 0.0;

            std::cout << "  " << std::setw(15) << std::left << ext << ": "
                      << std::setw(6) << count << " files, "
                      << std::setw(12) << formatBytes(size) << " "
                      << "(" << std::fixed << std::setprecision(1) << percentage << "%)" << std::endl;
        }

    } catch (const std::exception& e) {
        std::cerr << "Error analyzing directory: " << e.what() << std::endl;
    }
}

// 8. Search files by content pattern (simple text search)
void SearchFilesByContent(const std::string& directoryPath, const std::string& searchTerm)
{
    std::cout << "\n=== Search Files by Content ===" << std::endl;
    std::cout << "Directory: " << directoryPath << std::endl;
    std::cout << "Search term: '" << searchTerm << "'" << std::endl;

    int filesSearched = 0;
    int filesWithMatches = 0;
    int totalMatches = 0;

    try {
        std::vector<std::string> textExtensions = {".txt", ".log", ".cpp", ".h", ".html", ".css", ".js", ".xml", ".json"};

        for (const auto& entry : fs::recursive_directory_iterator(directoryPath)) {
            if (entry.is_regular_file()) {
                std::string ext = entry.path().extension().string();

                // Check if it's likely a text file
                if (std::find(textExtensions.begin(), textExtensions.end(), ext) != textExtensions.end() ||
                    ext.empty()) {

                    filesSearched++;

                    // Search in file (simple line-by-line search)
                    std::ifstream file(entry.path());
                    if (file.is_open()) {
                        std::string line;
                        int lineNum = 0;
                        bool fileHasMatch = false;

                        while (std::getline(file, line)) {
                            lineNum++;
                            if (line.find(searchTerm) != std::string::npos) {
                                if (!fileHasMatch) {
                                    std::cout << "\n📄 " << entry.path().filename().string() << std::endl;
                                    fileHasMatch = true;
                                    filesWithMatches++;
                                }

                                std::cout << "  Line " << lineNum << ": " << line << std::endl;
                                totalMatches++;
                            }
                        }

                        file.close();
                    }
                }
            }
        }

        std::cout << "\nSearch Results:" << std::endl;
        std::cout << "  Files searched: " << filesSearched << std::endl;
        std::cout << "  Files with matches: " << filesWithMatches << std::endl;
        std::cout << "  Total matches: " << totalMatches << std::endl;

    } catch (const std::exception& e) {
        std::cerr << "Error searching file contents: " << e.what() << std::endl;
    }
}

// Helper function to format bytes
std::string formatBytes(long long bytes) {
    const char* units[] = {"B", "KB", "MB", "GB", "TB"};
    double size = static_cast<double>(bytes);
    int unitIndex = 0;

    while (size >= 1024.0 && unitIndex < 4) {
        size /= 1024.0;
        unitIndex++;
    }

    std::ostringstream oss;
    oss << std::fixed << std::setprecision(2) << size << " " << units[unitIndex];
    return oss.str();
}

// Create test directory structure for demonstration
void CreateTestDirectoryStructure()
{
    std::cout << "Creating test directory structure..." << std::endl;

    // Create directories
    fs::create_directories("test_root/docs");
    fs::create_directories("test_root/images");
    fs::create_directories("test_root/code");
    fs::create_directories("test_root/code/subdir");

    // Create test files
    std::ofstream("test_root/readme.txt") << "This is a README file\n";
    std::ofstream("test_root/docs/manual.txt") << "User manual content\n";
    std::ofstream("test_root/docs/guide.txt") << "User guide content\n";
    std::ofstream("test_root/image1.png") << "Fake image content\n";
    std::ofstream("test_root/images/photo.jpg") << "Fake photo content\n";
    std::ofstream("test_root/main.cpp") << "#include <iostream>\nint main() { return 0; }\n";
    std::ofstream("test_root/code/helper.h") << "#pragma once\n";
    std::ofstream("test_root/code/subdir/utility.cpp") << "// Utility functions\n";
    std::ofstream("test_root/config.json") << "{\"version\": \"1.0\"}";
    std::ofstream("test_root/style.css") << "body { margin: 0; }\n";
    std::ofstream("test_root/script.js") << "console.log('Hello');\n";

    // Create some larger files
    for (int i = 0; i < 100; i++) {
        std::ofstream file("test_root/large_file_" + std::to_string(i) + ".txt");
        file << "This is large file " << i << "\n";
        for (int j = 0; j < 100; j++) {
            file << "Line " << j << " with some content\n";
        }
    }

    std::cout << "Test directory structure created." << std::endl;
}

// Cleanup test directory
void CleanupTestDirectory()
{
    try {
        if (fs::exists("test_root")) {
            fs::remove_all("test_root");
            std::cout << "\nTest directory cleaned up." << std::endl;
        }
    } catch (const std::exception& e) {
        std::cerr << "Error cleaning up test directory: " << e.what() << std::endl;
    }
}

int main()
{
    std::cout << "=== C++ Directory Traversal and File Listing ===" << std::endl;
    std::cout << "Demonstrating various directory operations\n" << std::endl;

    // Create test structure
    CreateTestDirectoryStructure();

    try {
        // Perform various directory operations
        ListDirectoryContents("test_root");

        RecursiveDirectoryTraversal("test_root", 2);

        CalculateDirectorySize("test_root");

        SearchFilesByPattern("test_root", R"(.*.txt)");
        SearchFilesByPattern("test_root", R"(.*.cpp)");

        FindRecentlyModifiedFiles("test_root", 1);

        FindDuplicateFiles("test_root");

        AnalyzeDirectoryStatistics("test_root");

        SearchFilesByContent("test_root", "include");

        std::cout << "\nAll directory operations completed successfully!" << std::endl;

    } catch (const std::exception& e) {
        std::cerr << "Unexpected error: " << e.what() << std::endl;
        return 1;
    }

    // Clean up
    CleanupTestDirectory();

    return 0;
}