C++ Chapter 18.6 : 기본적인 파일 입출력

Date:     Updated:

카테고리:

태그:

인프런에 있는 홍정모 교수님의 홍정모의 따라 하며 배우는 C++ 강의를 듣고 정리한 필기입니다. 😀
🌜 [홍정모의 따라 하며 배우는 C++]강의 들으러 가기!


chapter 18. 입력과 출력

기본적인 파일 입출력

🔔 파일 출력 (Writing)

아스키 포맷으로 파일 출력 (디폴트)

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cstdlib>		// for exit();
using namespace std;

int main()
{
	const string filename = "file.txt";

	// Writing
	if (true)
	{
		ofstream ofs(filename);
		if (!ofs) { std::cerr << "Making file error\n"; exit(EXIT_FAILURE);  }

		for (char i = 'a'; i <= 'z'; ++i)
			ofs << i ;
		ofs << '\n';
	}
}
  • it (true)
    • 무조건 거치게 되어 있는 if문이다.
    • 블록을 벗어나면 자동으로 ofs.close() 파일이 닫힐 수 있도록.
    • if(false)로 바꾸면 이 블록은 실행하지 않게 할수도 있으니 이렇게 if문에 넣어주면 편리하다.
  • ofstream ofs("file.txt)
    • file.txt 파일을 출력 스트림으로 삼는다. 이 파일에 흘려 보내 write 할 것임을 나타낸다.
  • if (!ofs) 파일을 열 수 없다면
    • ofs는 nullptr일 것
    • exit(1) 종료 시켜주기
  • for (char i = 'a'; i <= 'z'; ++i)
    • ofs << i ;
    • a~z 까지의 문자를 ofs 스트림에 보낸다. file.txt에 a~z 문자가 쓰여 저장됨.
  • 이제 프로젝트 위치와 같은 폴더에 가보면 file.txt 파일이 생겨있을 것이다!


바이너리로 파일 출력

  • 아스키 포맷으로 파일을 출력하는건 엄청 느리다.
  • 그래서 실무에선 바이너리로 저장하는 경우가 많다.

방법 1️⃣ ofstream의 write 사용

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cstdlib>		// for exit();
using namespace std;

int main()
{
	const string filename = "file.txt";

	// Writing
	if (true)
	{
		ofstream ofs(filename);
		if (!ofs) { std::cerr << "Making file error\n"; exit(EXIT_FAILURE);  }

		const unsigned num_data = 10;
		ofs.write((char*)&num_data, sizeof(num_data));

		for (int i = 0; i < num_data; ++i)
				ofs.write((char*)&i, sizeof(i)); 
	}
}
  • 바이너리로 저장할 땐 데이터가 어디까지 저장되는지 알 수가 없기 때문에 데이터가 몇 개를 저장할지, 얼마의 크기로 저장할지 미리 약속해야 한다.
    • 10개의 문자를 저장하고 싶다면
      • unsinged num_data = 10;
  • ofs.write(const char* str, streamsize n)
    • write 함수
      • 바이너리 값 그대로 ofs에 출력된다.
      • 첫번째 인수
        • char형 포인터나 주소값
        • (char*)&num_data
          • num_data 의 주소를 char*로 캐스팅하여 넘김
      • 두번째 인수
        • 출력할 byte 수
          • sizeof(num_data)
            • num_data 값만큼의 크기를 저장할거라고 약속하고 넘김
    • ofs 스트림인 file.txt 에 “10”이 바이너리로 쓰여지고 저장된다.
      • for (int i = 0; i < num_data; ++i) ofs.write((char*)&i, sizeof(i));
        • for문 10번 돌면서
          • 0 1 2 3 4 5 6 7 8 9 가 바이너리로 file.txt.에 저장될 것.
      • 최종적으로 file.txt 에 10 0 1 2 3 4 5 6 7 8 9 로 쓰여있음

방법 2️⃣ 파일 스트림 모드를 ios::binary로.

  • ofstream ofs (“file.txt”, ios:binary )


🔔 파일 입력 (Reading)

아스키 포맷으로 파일 입력 ( 디폴트 )

  • ifstream ifs("file.txt")
    • 프로젝트 위치와 같은 폴더에서 file.txt 파일을 파일 입력 스트림으로 불러온다.
  • if (!ifs)
    • 파일을 열지 못 한다면. 오류. ifs에 nullptr 들어가있을 것. exit로 종료해주자.
  • getline(ifs, str);
    • ifs 로부터 한줄 씩 읽어 들여 string str에 저장
    • 파일 끝 EOF에 도달하면 ifs가 EOF가 되어 while문 빠져 나옴.
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cstdlib>		// for exit();
using namespace std;

int main()
{
	const string filename = "file.txt";

	// Reading
	if (true)
	{
		ifstream ifs(filename);

		if (!ifs) { std::cerr << "Opening file error\n"; exit(EXIT_FAILURE);  }

		while (ifs)
		{
			std::string str;
			getline(ifs, str);

			std::cout << str << endl;
		}
	}
}


바이너리 파일 입력

  • 아스키 포맷으로 불러들이는건 너무 느리다

방법 1️⃣ ifstream의 read()이용

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cstdlib>		// for exit();
using namespace std;

int main()
{
	const string filename = "file.txt";

	// Reading
	if (true)
	{
		ifstream ifs(filename);

		if (!ifs) { std::cerr << "Opening file error\n"; exit(EXIT_FAILURE);  }

		const unsigned num_data = 0;
		ifs.read((char*)&num_data, sizeof(num_data));

		for (int i = 0; i < num_data; ++i)
		{
				int num;
				ifs.read((char*)&num, sizeof(num));
				std::cout << num << endl;
		}		
	}
}
  • const unsigned num_data = 0
    • 얼마 정도의 크기로 읽어 올지 아직 몰라서 0으로 초기화.
    • 미리 file.txt에 숫자 몇개 읽어들일지를 크기를 num_data에 저장해놓는다. - 10 0 1 2 3 4 5 6 7 8 9 로 쓰여있다고 가정. - 10 은 num_data에 - 0123456789 는 num 에 불러와질 것. - 몇개 읽어 들일지 10으로 이렇게 앞에 써놓고 저장해놓기 ( 암묵적인 약속 )
  • ifs.read(const char* str, streamsize n)
    • ifs.read((char*)&num_data, sizeof(num_data));
    • read 함수
      • 바이너리 값 그대로 스트림으로부터 입력해온다.
      • 첫번째 인수
        • char형 포인터나 주소값
        • (char*)&num_data
          • num_data 의 주소를 char*로 캐스팅하여 넘김
      • 두번째 인수
        • 입력할 byte 수. ifs인 file.txt로부터 num_data에 읽어들일 크기가 저장 된다.
        • sizeof(num_data)
          • 추출할 문자의 크기.
      • for문
        • num 변수에 파일로 부터 읽어들여서
        • 0 1 2 3 4 5 6 7 8 9 가 차례로 저장되고 각각 출력.


🔔 파일 모드

image

  • ios::app
    • append 하기. 파일이 이미 존재할 경우에는 이어서 write.
  • ios::binary
    • 바이너리 모드.


🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

댓글남기기