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

C++ 파일 입출력

C++ 파일 입출력 — 중급

C++ 파일 입출력

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

파일 입출력(I/O)은 소프트웨어 개발에서 매우 중요한 기술입니다. 데이터는 프로그램의 생명선이며, 사용자와의 상호작용, 데이터 저장 및 로드, 그리고 다양한 외부 시스템과의 연동을 위해서는 파일 입출력이 필수적입니다. 예를 들어, 데이터베이스에 저장된 정보를 가져오거나, 로그 파일에 오류 메시지를 기록하는 등 실무에서 자주 사용됩니다.

이 기술을 모르면, 프로그램이 종료될 때마다 데이터를 잃어버리거나 사용자의 요청에 따라 데이터를 처리하기 어려워집니다. 따라서 파일 입출력은 현대 프로그램에서 거의 모든 분야에서 필수적으로 요구되는 능력입니다.

2. 핵심 개념 설명

파일 입출력의 기본 개념은 다음과 같습니다:

  • 파일: 컴퓨터에 저장된 데이터의 집합으로, 텍스트 파일이나 바이너리 파일 등이 있습니다.
  • 스트림: 데이터의 흐름을 나타내며, 입력(읽기) 스트림과 출력(쓰기) 스트림으로 나뉩니다. 스트림은 마치 수도관처럼 데이터를 전달합니다.
  • 입력 스트림: 파일에서 데이터를 읽어오는 통로입니다.
  • 출력 스트림: 데이터를 파일에 쓰는 통로입니다.
  • 용어설명
    파일데이터를 저장하는 단위
    입력 스트림파일에서 데이터를 읽어오는 경로
    출력 스트림데이터를 파일에 쓰는 경로

    이해를 돕기 위해 비유를 하자면, 파일은 서랍에 저장된 문서와 같고, 스트림은 그 서랍에서 문서를 꺼내거나 다시 넣는 손과 같습니다. 잘못된 스트림 사용은 문서를 엉뚱한 곳에 두거나 잃어버리는 것과 같기 때문에 주의가 필요합니다.

    3. 기본 코드 예제

    다음은 C++에서 파일에 문자열을 쓰고, 다시 읽어오는 간단한 예제입니다.

    #include <iostream>
    #include <fstream>
    #include <string>
    
    int main() {
        // 파일에 문자열 쓰기
        std::ofstream outFile("example.txt"); // example.txt 파일을 쓰기 모드로 연다
        if (outFile.is_open()) { // 파일이 정상적으로 열렸는지 확인
            outFile << "안녕하세요, 파일 입출력입니다!\n"; // 파일에 문자열을 쓴다
            outFile.close(); // 파일을 닫는다
        }
    
        // 파일에서 문자열 읽기
        std::ifstream inFile("example.txt"); // example.txt 파일을 읽기 모드로 연다
        std::string line; // 문자열을 저장할 변수
        if (inFile.is_open()) { // 파일이 정상적으로 열렸는지 확인
            while (std::getline(inFile, line)) { // 파일에서 한 줄씩 읽는다
                std::cout << line << std::endl; // 읽은 내용을 출력한다
            }
            inFile.close(); // 파일을 닫는다
        }
    
        return 0; // 프로그램 종료
    }

    실행 결과

    안녕하세요, 파일 입출력입니다!

    코드 설명

    1. #include <iostream>: 입출력 스트림을 사용하기 위해 포함합니다.
    2. #include <fstream>: 파일 스트림을 사용하기 위해 포함합니다.
    3. std::ofstream outFile("example.txt");: "example.txt" 파일을 쓰기 모드로 엽니다.
    4. if (outFile.is_open()) { ... }: 파일이 정상적으로 열렸는지 확인하고, 열렸다면 내용을 씁니다.
    5. outFile << "안녕하세요, 파일 입출력입니다!\n";: 지정한 문자열을 파일에 씁니다.
    6. outFile.close();: 파일을 닫습니다.
    7. std::ifstream inFile("example.txt");: "example.txt" 파일을 읽기 모드로 엽니다.
    8. while (std::getline(inFile, line)) { ... }: 파일에서 한 줄씩 읽어와 변수에 저장합니다.
    9. std::cout << line << std::endl;: 읽어온 내용을 콘솔에 출력합니다.
    10. inFile.close();: 파일을 닫습니다.
    11. 4. 실전 활용 예제

      예제 1: 쇼핑몰 장바구니 구현

      쇼핑몰에서 사용자가 장바구니에 담은 상품 정보를 파일로 저장하고, 다음에 프로그램을 실행할 때 다시 불러오기 위해 파일 입출력을 사용할 수 있습니다.

      #include <iostream>
      #include <fstream>
      #include <vector>
      
      void saveCart(const std::vector<std::string>& cart) {
          std::ofstream outFile("cart.txt");
          for (const auto& item : cart) {
              outFile << item << std::endl; // 장바구니의 각 아이템을 파일에 기록
          }
          outFile.close();
      }
      
      std::vector<std::string> loadCart() {
          std::ifstream inFile("cart.txt");
          std::vector<std::string> cart;
          std::string item;
          while (std::getline(inFile, item)) {
              cart.push_back(item); // 파일에서 아이템을 읽어와 장바구니에 추가
          }
          inFile.close();
          return cart;
      }
      
      int main() {
          std::vector<std::string> cart = {"사과", "바나나", "오렌지"};
          saveCart(cart); // 장바구니 저장
      
          std::vector<std::string> loadedCart = loadCart(); // 장바구니 불러오기
          for (const auto& item : loadedCart) {
              std::cout << item << std::endl; // 불러온 장바구니 아이템 출력
          }
      
          return 0;
      }

      예제 2: 로그 파일 작성

      프로그램 실행 중 발생한 오류나 중요한 이벤트를 기록하기 위해 로그 파일을 작성할 수 있습니다. 이를 통해 문제를 분석하고 디버깅하는 데 도움이 됩니다.

      #include <iostream>
      #include <fstream>
      #include <string>
      
      void logEvent(const std::string& message) {
          std::ofstream logFile("log.txt", std::ios::app); // append 모드로 파일 열기
          if (logFile.is_open()) {
              logFile << message << std::endl; // 로그 메시지 기록
              logFile.close();
          }
      }
      
      int main() {
          logEvent("프로그램 시작");
          logEvent("사용자 데이터 로드 완료");
          logEvent("오류 발생: 파일을 찾을 수 없습니다.");
          
          return 0;
      }

      5. 흔한 실수와 주의사항

    12. 파일이 열리지 않을 때 처리 누락: 파일이 정상적으로 열리지 않으면 이후 작업에서 오류가 발생할 수 있습니다.
    13. - 잘못된 코드:

         std::ifstream inFile("nonexistent.txt");
         inFile >> data; // 파일 열기 실패 시 오류 발생

      - 올바른 코드:

         std::ifstream inFile("nonexistent.txt");
         if (!inFile) {
             std::cerr << "파일 열기 실패!" << std::endl; // 오류 메시지 출력
             return 1;
         }
    14. 파일 닫기 누락: 파일을 닫지 않으면 데이터가 저장되지 않거나 다른 문제를 일으킬 수 있습니다.
    15. - 잘못된 코드:

         std::ofstream outFile("example.txt");
         outFile << "데이터"; // 파일 닫기 누락

      - 올바른 코드:

         std::ofstream outFile("example.txt");
         outFile << "데이터";
         outFile.close(); // 반드시 닫아야 함
    16. 파일 모드 혼동: 쓰기 모드와 읽기 모드를 혼동하면 데이터가 손실될 수 있습니다.
    17. - 잘못된 코드:

         std::ofstream outFile("example.txt"); // 기존 파일 덮어쓰기

      - 올바른 코드:

         std::ofstream outFile("example.txt", std::ios::app); // 기존 파일에 추가

      6. 정리

    18. 파일 입출력은 데이터를 저장하고 불러오는 데 필수적입니다.
    19. 입출력 스트림을 통해 파일에 데이터를 읽고 쓸 수 있습니다.
    20. 파일이 열리지 않거나 닫지 않는 실수를 주의해야 합니다.
    21. 실무에서 장바구니 저장 및 로그 기록 등의 다양한 패턴으로 활용됩니다.
    22. 다음에 학습하면 좋은 주제

    23. 파일 입출력의 성능 최적화
    24. 바이너리 파일 입출력
    25. 파일 시스템과 데이터베이스 연동하기