IMCAT.DEV
로그인 가입
C++ 고급 자료구조

C++ C++의 고급 파일 I/O 처리

C++ C++의 고급 파일 I/O 처리 — 고급

C++의 고급 파일 I/O 처리

1. 도입 (왜 배워야 하는가)

C++에서 파일 I/O(Input/Output)는 데이터의 저장과 처리를 위해 필수적인 기술입니다. 특히, 대규모 애플리케이션이나 데이터베이스와 같은 실무 환경에서는 파일과의 원활한 상호작용이 중요합니다. 예를 들어, 사용자 데이터를 파일에 저장하고 불러오는 작업은 쇼핑몰, 게임, 또는 데이터 분석 프로그램에서 필수적입니다.

파일 I/O를 제대로 이해하지 못하면, 데이터가 손실되거나 프로그램이 예기치 않게 종료될 수 있습니다. 또한, 비효율적인 파일 처리로 인해 성능 저하가 발생할 수 있습니다. 이 때문에 고급 파일 I/O 처리를 배우는 것은 실무에서 매우 중요한 요소입니다.

2. 핵심 개념 설명

2.1. 파일 스트림

파일 스트림은 파일에 데이터를 읽거나 쓰기 위한 객체입니다. C++에서는 ifstream(Input File Stream)와 ofstream(Output File Stream), fstream(File Stream)을 제공합니다.

  • 비유: 파일 스트림은 마치 편지를 주고받는 우편함과 같습니다. ifstream은 편지를 받는 우편함, ofstream은 편지를 보내는 우편함이라고 생각할 수 있습니다.
  • 용어설명
    ifstream파일에서 데이터를 읽기 위한 스트림
    ofstream파일에 데이터를 쓰기 위한 스트림
    fstream파일에서 읽고 쓰기 모두 가능한 스트림

    2.2. 파일 열기 및 닫기

    파일을 사용하기 전에 반드시 열어야 하며, 사용이 끝난 후에는 닫아야 합니다. 파일을 열 때는 파일 경로와 모드를 지정해야 합니다.

  • 비유: 파일을 여는 것은 상자를 여는 것과 같고, 닫는 것은 상자를 다시 닫는 것과 같습니다.
  • 3. 기본 코드 예제

    파일을 열고 데이터를 쓰고 읽는 가장 기본적인 예제를 살펴보겠습니다.

    #include <iostream>
    #include <fstream>
    
    int main() {
        // 파일 쓰기
        std::ofstream outfile("example.txt");
        if (outfile.is_open()) {
            outfile << "Hello, File I/O!" << std::endl; // 파일에 문자열 쓰기
            outfile.close(); // 파일 닫기
        } else {
            std::cerr << "파일을 열 수 없습니다!" << std::endl;
        }
    
        // 파일 읽기
        std::ifstream infile("example.txt");
        std::string line;
        if (infile.is_open()) {
            while (getline(infile, line)) { // 한 줄씩 읽기
                std::cout << line << std::endl; // 읽은 줄 출력
            }
            infile.close(); // 파일 닫기
        } else {
            std::cerr << "파일을 열 수 없습니다!" << std::endl;
        }
    
        return 0;
    }

    실행 결과

    Hello, File I/O!

    코드 한 줄씩 동작 설명

    1. #include <iostream>: 입출력 스트림을 사용하기 위한 헤더 파일 포함.
    2. #include <fstream>: 파일 입출력을 위한 헤더 파일 포함.
    3. std::ofstream outfile("example.txt");: "example.txt"라는 이름의 파일을 쓰기 모드로 연다.
    4. if (outfile.is_open()) {...}: 파일이 정상적으로 열렸는지 확인한다.
    5. outfile << "Hello, File I/O!" << std::endl;: 파일에 문자열을 쓴다.
    6. outfile.close();: 파일을 닫는다.
    7. std::ifstream infile("example.txt");: "example.txt" 파일을 읽기 모드로 연다.
    8. if (infile.is_open()) {...}: 파일이 정상적으로 열렸는지 확인한다.
    9. while (getline(infile, line)) {...}: 파일에서 한 줄씩 읽어와서 line 변수에 저장한다.
    10. std::cout << line << std::endl;: 읽은 줄을 콘솔에 출력한다.
    11. infile.close();: 파일을 닫는다.
    12. 4. 실전 활용 예제

      4.1. 로그 파일 작성

      애플리케이션에서 발생하는 이벤트를 기록하기 위한 로그 파일을 작성할 수 있습니다. 예를 들어, 웹 서버에서 요청을 처리할 때마다 로그를 남길 수 있습니다.

      #include <iostream>
      #include <fstream>
      #include <ctime>
      
      void logEvent(const std::string& event) {
          std::ofstream logfile("server.log", std::ios::app); // append 모드로 열기
          if (logfile.is_open()) {
              std::time_t now = std::time(nullptr); // 현재 시간
              logfile << std::ctime(&now) << ": " << event << std::endl; // 시간과 이벤트 기록
              logfile.close();
          }
      }
      
      int main() {
          logEvent("사용자가 로그인했습니다.");
          logEvent("사용자가 상품을 조회했습니다.");
          return 0;
      }

      4.2. 사용자 데이터 저장

      사용자 정보를 파일에 저장하고 불러오는 예제입니다. 쇼핑몰에서 장바구니 정보를 저장할 때 유용합니다.

      #include <iostream>
      #include <fstream>
      #include <vector>
      
      struct Product {
          std::string name;
          double price;
      };
      
      void saveCart(const std::vector<Product>& cart) {
          std::ofstream outfile("cart.txt");
          for (const auto& product : cart) {
              outfile << product.name << "," << product.price << std::endl; // 이름과 가격 저장
          }
          outfile.close();
      }
      
      std::vector<Product> loadCart() {
          std::ifstream infile("cart.txt");
          std::vector<Product> cart;
          std::string line;
          while (getline(infile, line)) {
              size_t pos = line.find(',');
              if (pos != std::string::npos) {
                  Product product;
                  product.name = line.substr(0, pos); // 이름 추출
                  product.price = std::stod(line.substr(pos + 1)); // 가격 추출
                  cart.push_back(product);
              }
          }
          infile.close();
          return cart;
      }
      
      int main() {
          std::vector<Product> cart = {{"Apple", 0.99}, {"Banana", 0.59}};
          saveCart(cart); // 장바구니 저장
      
          std::vector<Product> loadedCart = loadCart(); // 장바구니 불러오기
          for (const auto& product : loadedCart) {
              std::cout << product.name << ": $" << product.price << std::endl; // 출력
          }
          return 0;
      }

      5. 흔한 실수와 주의사항

      5.1. 파일 경로 오류

    13. 잘못된 코드:
    14.   std::ofstream outfile("wrong_path/example.txt");
    15. 올바른 코드:
    16.   std::ofstream outfile("C:/correct_path/example.txt");

      5.2. 파일 닫기를 잊음

      파일을 닫지 않으면 데이터가 손실될 수 있습니다.

    17. 잘못된 코드:
    18.   std::ofstream outfile("example.txt");
        outfile << "Data";
        // outfile.close(); // 닫기 누락
    19. 올바른 코드:
    20.   std::ofstream outfile("example.txt");
        outfile << "Data";
        outfile.close(); // 항상 닫기

      5.3. 읽기 전 파일 열기 확인 누락

      파일을 읽기 전에 열었는지 확인하지 않으면 에러가 발생합니다.

    21. 잘못된 코드:
    22.   std::ifstream infile("example.txt");
        std::string line;
        getline(infile, line); // 열기 확인 없이 읽기
    23. 올바른 코드:
    24.   std::ifstream infile("example.txt");
        if (infile.is_open()) {
            std::string line;
            getline(infile, line); // 정상적으로 파일이 열렸을 때만 읽기
        }

      6. 정리

    25. C++의 파일 I/O는 데이터 저장과 처리를 위해 필수적이다.
    26. ifstream, ofstream, fstream을 통해 파일을 읽고 쓸 수 있다.
    27. 파일을 열고 닫는 것을 잊지 말아야 하며, 경로와 모드 설정이 중요하다.
    28. 로그 파일, 사용자 데이터 저장 등 다양한 실무 활용 사례가 있다.

다음에 학습하면 좋은 주제는 C++의 메모리 관리 및 예외 처리입니다. 이 두 가지는 파일 I/O와 함께 프로그램의 안정성과 성능을 극대화하는 데 큰 도움이 됩니다.