객체지향프로그래밍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 사용
- >> 연산자와 istream의 get, read() 함수
◼ 연결된 장치로부터 읽는 함수
◼ 키보드에 연결되면 키 입력을, 파일에 연결되면 파일에서 입력 - << 연산자와 ostream의 put(), write() 함수
◼ 연결된 장치에 쓰는 함수
◼ 스크린에 연결되면 화면에, 파일에 연결되면 파일에 출력
파일 입출력 모드 : 텍스트 I/O와 바이너리 I/O
- 파일 입출력 방식
- 텍스트 I/O와 바이너리 I/O의 두 방식
◼ C++ 파일 입출력 클래스(ifstream, ofstream, fstream)는 두 방식 지원
- 텍스트 I/O와 바이너리 I/O의 두 방식
- 텍스트 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;
}
텍스트 파일의 라인 단위 읽기
- istream의 getline(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) 위치를 기준으로 파일 포인터를 움직인다. |