[C++] IO (fstream)(파일 읽기 쓰기)를 사용하는 방법


Study/C , C++ , MFC  2020. 4. 6. 16:44

안녕하세요. 명월입니다.


이 글은 C++에서 IO(파일 읽기 쓰기)를 사용하는 방법에 대한 글입니다.


IO의 약어의 해석은 Input/Output의 뜻으로 사실 Input 장치인 키보드, 마우스 등등, Output장치인 모니터를 뜻하는 말입니다.

하지만 프로그램에서는 파일을 다루는 라이브러리를 통칭하는 의미합니다.


C++에서 파일을 읽고 쓰기에 대해서는 사실 굉장히 간단한 함수가 있습니다. fopen과 fwrite, fread를 통해서 사용할 수 있습니다.

// fopen, fwrite, fread를 최신 버전에서 사용하면 unsafe(안전하지 않은) 경고와 deprecation의 에러가 발생한다.
// 즉, 더이상 사용을 권하지 않는 뜻이다.
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <iostream>
using namespace std;
// 실행 함수
int main()
{
  // 파일 리소스 포인터를 취득, 파라미터 w는 작성이다. (리소스 취득)
  FILE* fp = fopen("d:\\work\\test.txt", "w");
  // 포인터가 null이면 프로그램을 종료한다.
  if (fp == NULL) {
  	cout << "File open failed" << endl;
  	return 1;
  }
  // 유니코드로 된 변수를 선언한다.
  const wchar_t* data1 = L"hello world";
  // 파일에 문자열을 작성한다. 유니코드라 사이즈는 2배이다.
  fwrite(data1, 1, wcslen(data1) * 2, fp);
  // 파일을 닫는다. (리소스 반환)
  fclose(fp);
  // 콘솔 출력
  cout << "The file was created." << endl;
  // 파일 리소스 포인터를 취득, 파라미터 r는 읽기이다. (리소스 취득)
  fp = fopen("d:\\work\\test.txt", "r");
  // 포인터가 null이면 프로그램을 종료한다.
  if (fp == NULL) {
  	cout << "File open failed" << endl;
  	return 1;
  }
  // 파일 위치 포인터를 끝으로 이동한다.
  fseek(fp, 0, SEEK_END);
  // 위치 포인트의 위치를 리턴한다. 유니코드이므로 위치 * 2하면 파일 사이즈가 된다.
  int size = ftell(fp) * 2;
  // 파일 사이즈로 유니코드 char를 선언한다.
  wchar_t* data2 = new wchar_t[size];
  // 파일 위치 포인터를 앞으로 이동한다.
  fseek(fp, 0, SEEK_SET);
  // 파일을 읽는다.
  fread(data2, 1, size, fp);
  // 결과 콘솔 출력
  wcout << "Result : " <<data2 << endl;
  // 파일을 닫는다. (리소스 반환)
  fclose(fp);
  // 메모리 해제
  delete data2;
  
  return 0;
}

파일이 정상적으로 생성되고 읽어 왔습니다.

참조 - http://www.cplusplus.com/reference/cstdio/fopen/

그러나 이게 deprecation되어서 더이상 사용하기를 권장하지 않는다고 합니다. 그럼, 다른 방법으로 IO를 취득해서 파일을 읽고 작성해야 하겠습니다.


c++에는 IO를 다룰 수 있는 fstream 라이브러리가 있습니다.

#include <stdio.h>
#include <iostream>
// fstream을 include한다.
#include <fstream>
using namespace std;
// 실행 함수
int main()
{
  // 유니코드로 된 변수를 선언한다.
  const wchar_t* data1 = L"hello world";
  // output stream을 선언한다. ※클래스 앞에 w가 붙는 건 유니코드 용이다.
  wofstream ostream;
  // d:\\work\\new.txt에 작성한다. , 디폴트 파라미터는 텍스트 파일이지만 바이너리를 다룰 때는 ios::binary를 추가한다.
  ostream.open("d:\\work\\new.txt");
  // 파일에 텍스트를 작성한다.
  ostream << data1;
  // stream를 닫는다. (리소스 반환)
  ostream.close();

  // 파일 사이즈를 구하기 위한 seek 위치를 구한다.
  wstreampos begin, end;
  // input stream을 선언한다.
  wifstream istream("d:\\work\\new.txt");
  // stream의 seek position을 구한다.
  begin = istream.tellg();
  // stream의 seek position을 파일 맨 끝으로 이동한다.
  istream.seekg(0, ios::end);
  // stream의 seek position을 구한다.
  end = istream.tellg();
  // stream의 seek position을 파일 앞 끝으로 이동한다.
  istream.seekg(0, ios::beg);
  // 파일 사이즈 구하기
  int size = end - begin;
  // 파일 내용을 담을 변수 선언
  wchar_t* data2 = new wchar_t[size];
  // 파일 내용을 변수에 담는다.
  istream.read(data2, size);
  // 결과 콘솔 출력
  wcout << "Result : " << data2 << endl;
  // stream를 닫는다. (리소스 반환)
  istream.close();
  // 메모리 해제
  delete data2;

  return 0;
}

파일이 정상적으로 생성되고 읽어 왔습니다.

참조 - http://www.cplusplus.com/doc/tutorial/files/


저도 C++를 사용 안 한 지가 벌써 10년이 되었습니다. 그 사이에 IO에 대한 사용법도 바뀌었네요.

개인적으로 fopen과 fread, fwrite도 편했는데.. 많은 문제가 있는 것 같습니다.

IO의 주요할 점은 꼭 close로 리소스를 반환 해야 합니다. 그렇지 않으면 성능상에 문제가 발생할 수 있습니다.

C++은 try finally가 없으니깐 조심해야 겠습니다.


여기까지 C++에서 IO(파일 읽기 쓰기)를 사용하는 방법에 대한 글이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.