본문 바로가기

Programming/C C++

[C, C++] File처리

C++에서 File을 처리하기 위한 Class로는 ifstream(읽기), ofstream(쓰기), fstream(읽기, 쓰기)가 있으며 이 세개의 Class는 fstream.h 안에 정의되어 있습니다.

#include <fstream.h>
▶File처리 Class를 사용하기 위해 fstream.h Header File을 선언합니다.

Header File을 선언하고 나면 목적에 맞는 용도에 따라 원하는 Class에 대한 Object를 생성합니다. (Class라는 것을 바로 사용하는 경우는 없습니다. 그것은 C++뿐만 아니라 Class개념을 사용하는 거의 대부분의 언어가 다 마찬가지 입니다.)

ifstream rd_file;
ofstream wd_file;

File로 부터 Data를 읽기위해 ifstream Class로부터 rd_file Object를 생성하고 Data를 쓰기위해 ofstream Class로부터 wd_file Object를 생성하였습니다.

File처리 Class로부터 Object를 생성하고 나면 이제 File조작은 이 Object를 통해서 진행하게 됩니다.

생성된 Object로부터 File을 열려면 open Member함수를 사용합니다.

wd_file.open("test.txt");

in_file Object로 부터 open함수를 불러와 test.txt File을 open합니다.

File을 open하고 원하는 작업이 모두 끝나고 나면 close()함수를 사용하여 열려진 File을 다음과 같이 닫아야 합니다.

wd_file.close();

File을 open하는 경우 open함수에 인수를 추가하면 File을 목적에 맞는 형태로 open 할 수 있습니다.

다음은 File의 open형태를 지정하는 인수과 사용예입니다.

 인수  설명
 ios::binary  binary 전용
 ios::in  읽기형태로 file을 open합니다. 만일 file이 존재하지 않는 경우 해당 file을 신규로 생성합니다.(in은 입력을 의미합니다. 즉, file에 있는 data를 외부로 입력하는 것입니다.)
 ios::nocreate  file open을 시도하지 않고 file이 있는지 여부만 판단합니다. file이 존재하지 않으면 error입니다..(신규로 생성하지 않습니다.)
<읽기용>

 인수  설명
 ios::app  file에 내용을 추가하기 위해 open합니다.
 ios::ate  file의 마지막부터 data를 씁니다.
 ios::binary  binary 전용
 ios::nocreate  읽기용과 같음
 ios::noreplace  nocreate과 반대입니다. file이 존재하면 error를 발생시킵니다.
 ios::out  쓰기용으로 file을 open합니다.
<쓰기용>

#include <iostream.h>
#include <fstream.h>

main()
{
  ofstream wd_file;
  wd_file.open("test.txt", ios::out);
 
  wd_file.put('a');
  wd_file.close();
  return 0;
}


test.txt 라는 File을 쓰기용으로 open하고 문자 a를 File에 씁니다.


만일 File open시 open형태에 대한 인수를 지정해 주지 않으면 기본값으로 읽기용엔 ios:in이 쓰기용엔 ios::out이 자동으로 지정됩니다.

또한 여러 형태에 대한 인수를 한번에 지정해 주고자 한다면 | 문자로 구분하여 인수를 지정해야 합니다.

#include <iostream.h>
#include <fstream.h>

main()
{
  ofstream wd_file;
  wd_file.open("test.txt", ios::out | ios::nocreate);
 
  wd_file.put('a');
  wd_file.close();
  return 0;
}


test.txt File을 쓰기용(ios::out)으로 open하되 File이 없으면 오류(ios::nocreate)입니다.

ios::nocreate라고 하면 File이 존재하지 않을 경우 오류라고 하였지만 Program이 알아서 오류에 대한 어떤 처리를 해주진 않습니다. 따라서 이 부분은 개발자가 직접 처리해야 합니다.

#include <iostream.h>
#include <fstream.h>

main()
{
  ofstream wd_file;
  wd_file.open("test.txt", ios::out | ios::nocreate);
 
  if (wd_file.fail()){
    cout << "file이 존재하지 않습니다." << endl;
   
    return 0;
  }
 
  wd_file.put('a');
  wd_file.close();
  return 0;
}


ios::nocreate로 File이 없으면 Error를 발생하도록 합니다. 이후 if문을 통해 File open이 실패했는지 확인(fail())하고 실패라면 지정한 Message를 출력한뒤 Program을 종료합니다.

▶test.txt File을 삭제 후 Program실행

오류에 대한 판단은 ios::nocreate를 했을경우에만 사용가능한 것은 아니며 오류의 종류 또한 fail()이외에 다음과 같은 여러가지가 있습니다.

 error 항목  설명
 bad  file처리 오류입니다.(fail보다 심각도가 더 높으며 초기화가 어렵습니다.)
 clear  발생한 오류상태를 초기화 합니다.
 eof  현재 file의 끝에 도달하였습니다.
 fail  file처리 오류입니다.(bad보다 심각도가 낮으며 초기화가 가능합니다.)
 good  file처리상태가 정상입니다.

쓰기용으로 File을 open한 경우 해당 File에 Data를 쓰기 위해서는 cout에서처럼 << 을 사용해 Data를 작성합니다.

#include <iostream.h>
#include <fstream.h>

main()
{
  ofstream wd_file;
  wd_file.open("test.txt", ios::out | ios::nocreate);
 
  if (wd_file.fail()){
    cout << "file이 존재하지 않습니다." << endl;
   
    return 0;
  }
 
  wd_file << "hello" << endl << "world";
  wd_file.close();
  return 0;
}


File 쓰기용 wd_file Object를 통해 test.txt File에 hello world문자열을 작성합니다.


반대로 읽을때는 >> 를 사용해야 합니다.

#include <iostream.h>
#include <fstream.h>

main()
{
  ifstream rd_file;
  char s[80];
 
  rd_file.open("test.txt", ios::in | ios::nocreate);
 
  if (rd_file.fail()){
    cout << "file이 존재하지 않습니다." << endl;
   
    return 0;
  }
 
  while (!rd_file.eof()){
      rd_file >> s;
      cout << s << endl;
  }
 
  rd_file.close();
  return 0;
}

▶File 읽기용 rd_file Object를 통해 File의 내용을 읽습니다.

위에서 File을 읽을때는 While문을 통하여 처음부터 끝까지 순차적으로 읽도록 하였습니다. While 문의 조건에는 !rd_file.eof() 를 사용해 File의 끝이 아닌경우 계속 읽어서 s 배열에 읽은 내용을 저장하고 다시 cout를 통해 해당 s의 내용을 출력하도록 하였습니다.


File 읽기에는 << 을 통해서 뿐만 아니라 get이나 getline함수를 이용할 수 도 있습니다. get은 문자를 getline은 문자열용입니다.

#include <iostream.h>
#include <fstream.h>

main()
{
  ifstream rd_file;
  char c;
 
  rd_file.open("test.txt", ios::in | ios::nocreate);
 
  if (rd_file.fail()){
    cout << "file이 존재하지 않습니다." << endl;
   
    return 0;
  }
 
  while (!rd_file.eof()){
      rd_file.get(c);
      cout << c << endl;
  }
 
  rd_file.close();
  return 0;
}

▶get을 통해 File로 부터 한문자씩 읽습니다.


#include <iostream.h>
#include <fstream.h>

main()
{
  ifstream rd_file;
  char s[80];
 
  rd_file.open("test.txt", ios::in | ios::nocreate);
 
  if (rd_file.fail()){
    cout << "file이 존재하지 않습니다." << endl;
   
    return 0;
  }
 
  while (!rd_file.eof()){
      rd_file.getline(s, 80);
      cout << s << endl;
  }
 
  rd_file.close();
  return 0;
}


getline함수를 통해 문자열을 80자까지 읽도록 합니다. 필요하다면 문자열 수는 더 크게 지정해 줄 수 있습니다.(단, 배열의 크기가 그 만큼 확보되어 있어야 합니다.)


다음은 사용자로 부터 한문자씩 입력받고 입력받은 내용을 출력하는 예제입니다.

#include <iostream.h>
#include <fstream.h>

main()
{
  ofstream wd_file;
  char c;
 
  wd_file.open("test.txt", ios::out);
 
  while (!wd_file.fail()){
      cout << "입력내용 : "; cin >> c;
     
      if (c == 'q')
        return 0;
     
      wd_file << c;
  }
 
  wd_file.close();
  return 0;
}


사용자로 부터 한문자씩 입력받고 입력받은 내용을 File에 저장합니다.

위 Program에서 입력 Data형식을 char형으로 하였습니다.

만일 Program을 중지하고자 한다면 q를 입력합니다.(if문을 통해 q가 입력되면 입력을 중지하도록 하였습니다.)

사용자가 q를 입력하지 않은 이상은 While문에 의해 계속 입력과 출력이 반복될 것입니다.(While문에서 조건을 1로 하였습니다.)



다음은 File읽기 쓰기 Object를 활용한 File복사의 예입니다.

#include <iostream.h>
#include <fstream.h>

main()
{
  ifstream rd_file;
  ofstream wd_file;
  char c;
 
  rd_file.open("test.txt", ios::in);
  wd_file.open("test2.txt", ios::out);
 
  while(!rd_file.eof()){
    rd_file.get(c);
    wd_file << c;
  }
 
  rd_file.close();
  wd_file.close();
 
  return 0;
}


rd_file의 get함수를 통해서 File로 부터 한문자를 읽고 test2.txt(wd_file) File에 읽은 문자를 작성합니다.



그런데 위 Program에서 File을 읽고 쓰기 위해 문자가 아닌 문자배열을 통하여 다음과 같이 하면 될것 같지만

#include <iostream.h>
#include <fstream.h>

main()
{
  ifstream rd_file;
  ofstream wd_file;
  char s[80];
 
  rd_file.open("test.txt", ios::in);
  wd_file.open("test2.txt", ios::out);
 
  while(!rd_file.eof()){
    rd_file >> s
    wd_file << s;
  }
 
  rd_file.close();
  wd_file.close();
 
  return 0;
}

▶배열을 통한 File의 입/출력을 구현

실제로 이렇게 작성한 Program은 원하는 결과를 제대로 얻을 수 없습니다. 문자를 읽는 get()함수와는 달리 이 Program은 공백을 포함시키지 않기 때문입니다.(따라서 공백을 제외해도 좋다면 위와같이 작성해도 될것입니다.)