devRenio

C++ 파일 입출력

객체지향프로그래밍II(김정준) 13주차 강의내용

텍스트 파일과 바이너리 파일

파일 : 연속된 바이트의 집합.

텍스트 파일

  • 사람들이 사용하는 글자 혹은 문자들로만 구성되는 파일
    • 알파벳, 한글, 숫자, % # @ < ? 등의 기호 문자
  • ‘\n’, ‘\t’ 등의 특수 문자도 포함
  • 각 문자마다 문자 코드(이진수) 할당
    • ASCII 코드, 유니코드
  • 텍스트 파일의 종류
    • txt 파일, HTML 파일, XML 파일, C++ 소스 파일, C 소스 파일, 자바 소스 파일
  • 텍스트 파일과 <Enter> 키
    • <Enter>키를 입력하면 텍스트 파일에는 ‘\r’, ‘\n’의 두 코드가 기록됨

바이너리 파일

  • 문자로 표현되지 않는 바이너리 데이터가 기록된 파일
    • 이미지, 오디오, 그래픽, 컴파일된 코드는 문자로 표현되지 않음
  • 텍스트 파일의 각 바이트 -> 문자로 해석
  • 바이너리 파일의 각 바이트 -> 문자로 해석되지 않는 것도 있음
    • 각 바이트의 의미는 파일을 만든 응용프로그램 만이 해석 가능
  • 바이너리 파일의 종류
    • jpeg, bmp 등의 이미지 파일
    • mp3 등의 오디오 파일
    • hwp, doc, ppt 등의 확장자를 가진 멀티미디어 문서 파일
    • obj, exe 등의 확장자를 가진 컴파일된 코드나 실행 파일


C++ 표준 파일 입출력 라이브러리

istream, ostream의 부모 클래스인 ifstream, ofstream 사용 iostream의 부모 클래스인 fstream 사용

  • >> 연산자와 istreamget, read() 함수
    ◼ 연결된 장치로부터 읽는 함수
    ◼ 키보드에 연결되면 키 입력을, 파일에 연결되면 파일에서 입력
  • << 연산자와 ostreamput(), write() 함수
    ◼ 연결된 장치에 쓰는 함수
    ◼ 스크린에 연결되면 화면에, 파일에 연결되면 파일에 출력

파일 입출력 모드 : 텍스트 I/O와 바이너리 I/O

  • 파일 입출력 방식
    • 텍스트 I/O와 바이너리 I/O의 두 방식
      ◼ C++ 파일 입출력 클래스(ifstream, ofstream, fstream)는 두 방식 지원
  • 텍스트 I/O
    • 문자 단위로 파일에 쓰기, 파일에서 읽기
      ◼ 문자를 기록하고, 읽은 바이트를 문자로 해석
    • 텍스트 파일에만 적용
  • 바이너리 I/O
    • 바이트 단위로 파일에 쓰기, 파일에서 읽기
      ◼ 데이터를 문자로 해석하지 않고 있는 그대로 기록하거나 읽음
    • 텍스트 파일과 바이너리 파일 모두 입출력 가능
  • 텍스트 I/O와 바이너리 I/O 입출력 시 차이점
    • 개행 문자(‘\n’) 사용법에서의 차이
    • 텍스트 I/O : ‘\n’을 ‘\r’, ‘\n’으로 처리
    • 바이너리 I/O : ‘\n’을 ‘\n’으로 처리

① open(경로/파일이름, 용도지정)
② 읽기/쓰기
③ close()

ofstream fout;
fout.open("c:\\temp\\test.txt");
fout << "Hello World" << endl;
fout.close();
ifstream fin;
fin.open("c:\\temp\\test.txt");
fin >> text;
cout << text << endl;
fin.close();


파일 모드(file mode)

  • 파일 입출력에 대한 구체적인 작업 행태에 대한 지정
  • 사례)
    ◼ 파일에서 읽을 작업을 할 것인지, 쓰기 작업을 할 것인지
    ◼ 기존 파일의 데이터를 모두 지우고 쓸 것인지, 파일의 끝 부분에 쓸 것인지
    ◼ 텍스트 I/O 방식인지 바이너리 I/O 방식인지
    ◼ | 를 이용하여 여러 파일 모드 동시 지정 가능
  • 파일 모드 지정 – 파일 열 때
    ◼ open(“파일이름”, 파일모드)
    ◼ ifstream(“파일이름”, 파일모드),
    ◼ ofstream(“파일이름”, 파일모드)
파일 모드 의미
ios::in 읽기 위해 파일을 연다.
ios::out 쓰기 위해 파일을 연다.
ios::ate (at end) 쓰기 위해 파일을 연다. 열기 후 파일 포인터를 파일 끝에 둔다. 파일 포인터를 옮겨 파일 내의 임의의 위치에 쓸 수 있다.
ios::app 파일 쓰기 시에만 적용된다. 파일 쓰기 시마다, 자동으로 파일 포인터가 파일 끝으로 옮겨져서 항상 파일의 끝에 쓰기가 이루어진다.
ios::trunc 파일을 열 때, 파일이 존재하면 파일의 내용을 모두 지워 파일 크기가 0인 상태로 만든다. ios::out 모드를 지정하면 디폴트로 함께 지정된다.
ios::binary 바이너리 I/O로 파일을 연다. 이 파일 모드가 지정되지 않으면 디폴트가 텍스트 I/O이다.
fout.open("student.txt", ios::out | ios::app); // out과 app 모드 동시 지정
  • 파일의 끝에서 읽기를 시도하면 get()은 EOF(-1값)를 리턴
while((c = fin.get()) != EOF) { // EOF를 만날 때까지 문자 읽기
  cout << (char)c;
}


텍스트 파일의 라인 단위 읽기

  • istreamgetline(char* line, int n) 함수 이용
  • getline(ifstream& fin, string& line) 함수 이용
while(fin.getline(buf, 81)) { // 한 라인이 최대 80개의 문자로 구성
  cout << buf << endl; // 라인 출력
}


바이너리 I/O

  • 데이터의 바이너리 값을 그대로 파일에 저장하거나, 파일의 바이너리 값을 그대로 읽어서 변수나 버퍼에 저장하는 방식
  • 텍스트 파일이든 바이너리 파일이든 바이너리 I/O로 입출력가능
  • ios::binary 모드 속성 사용
    ios::binary가 설정되지 않으면 디폴트가 텍스트 I/O

  • get()/put()
    • 문자 혹은 바이트 단위로 파일 입출력
  • read()/write()
    • 블록 단위로 파일 입출력


스트림 상태

  • 파일 입출력이 진행되는 동안 스트림(열어 놓은 파일)에 관한 입출력 오류 저장
    ◼ 스트림 상태를 저장하는 멤버 변수 이용
비트 설명
eofbit 파일의 끝을 만났을 때 1로 세팅
failbit 정수를 입력받고자 하였으나 문자열이 입력되는 등 포맷 오류나, 쓰기 금지된 곳에 쓰기를 시행하는 등 전반적인 I/O 실패 시에 1로 세팅
badbit 스트림이나 데이터가 손상되는 수준의 진단되지 않는 문제가 발생한 경우나 유효하지 않는 입출력 명령이 주어졌을 때 1로 세팅
멤버 함수 설명
eof() 파일의 끝을 만났을 때(eofbit=1) true 리턴
fail() failbit나 badbit가 1로 세팅되었을 때 true 리턴
bad() badbit이 1로 세팅되었을 때 true 리턴
good() 스트림이 정상적(모든 비트가 0)일 때 true 리턴
clear() 스트림 상태 변수를 0으로 지움


임의 접근과 파일 포인터

  • C++ 파일 입출력 방식
    • 순차 접근
      ◼ 읽은 다음 위치에서 읽고, 쓴 다음 위치에 쓰는 방식
      ◼ 디폴트 파일 입출력 방식
    • 임의 접근
      ◼ 파일 내의 임의의 위치로 옮겨 다니면서 읽고 쓸 수 있는 방식
      ◼ 파일 포인터를 옮겨 파일 입출력
  • 파일 포인터(file pointer)
    • 파일 포인터
      ◼ 파일에서 다음에 읽거나 쓸 위치를 표시하는 특별한 마크
    • C++는 열려진 파일마다 두 개의 파일 포인터 유지
      get pointer : 파일 내에 다음에 읽을 위치
      put pointer : 파일 내에 다음에 쓸 위치
// 정수 값으로 주어진 절대 경로 pos로 get pointer를 옮김
istream& seekg(streampos pos)

// seekbase를 기준으로 offset만큼 떨어진 위치로 get pointer를 옮김
istream& seekg(streamoff offset, ios::seekdir seekbase)

// 정수 값으로 주어진 절대 경로 pos로 put pointer를 옮김
ostream& seekp(streampos pos)

// seekbase를 기준으로 offset만큼 떨어진 위치로 put pointer를 옮김
ostream& seekp(streamoff offset, ios::seekdir seekbase)

//입력 스트림의 현재 get pointer의 값 리턴
streampos tellg()

// 출력 스트림의 현재 put pointer의 값 리턴
streampos tellp()
seekbase 설명
ios::beg 파일의 처음 위치를 기준으로 파일 포인터를 움직인다.
ios::cur 현재 파일 포인터의 위치를 기준으로 파일 포인터를 움직인다.
ios::end 파일의 끝(EOF) 위치를 기준으로 파일 포인터를 움직인다.