본문 바로가기

컴퓨터공학/C, C++

C,C++> 파일 입출력

파일

운영체제나 컴파일러는 파일을 접근할 수 있는 함수를 제공하며 프록램은 이 함수를 호출하여 원하는 파일을 읽고 사용한다. 파일 접근 방법은 여러 가지 종류가 있다.

1. 고수준 입출력 스트림 사용 :

C 라이브러리가 제공하는 파일 입출력 방법. 성능은 떨이지지만 사용하기 쉽다. 표준 함수 형태가 고정되어 있어서 이식에 유리

2. 저수준 파일 핸들 :

C 라이브러리가 제공하는 파일 입출력 방법. 대규모 데이터를 다룰 때 편리하다.

3. C++ 스트림 객체 :

ifstream, ofstream 등 입출력 객체와 그 멤버 함수를 사용하여 파일 액세스한다. 

4. 운영체제가 제공하는 API 함수 :

디스크 관리 주체는 운영체제이며 응용 프로그램을 위해 운영체제는 API 함수를 제공한다. 윈도우는 CreateFile, ReadFile, WriteFile 등 함수를 제공한다.

5. 클래스 라이브러리가 제공하는 파일 액세스 객체 사용 : 

고수준 클래스 라이브러리는 파일 액세스 기능을 캡슐화한 클래스를 제공한다. 

 

고수준 파일 입출력

버퍼는 입출력 데이터를 잠시 저장하는 메모리 영역이다. 

스트림은 흐름을 의미한다. 바이트들이 순서대로 입출력되는 논리적인 장치를 스트림이라고 한다.

파일에도 바이트들이 저장되어 있으며 읽을 때나 쓸 때 순서대로 바이트들이 입출력되므로 스트림이라고 할 수 있다. 

키보드, 화면, 프린트 등 장비들도 바이트들이 순서대로 흘러 다니므로 일종의 스트림이다.

스트림은 내부에 입출력 버퍼를 갖고 있다. 이 버퍼는 스트림에 의해 관리되므로 버퍼를 준비하거나 관리할 필요가 없다. 

어떤 스트림으로부터 얼마나 데이터를 읽거나 쓰고 싶다는 의사 표현을 하면 필요한 동작은 스트림이 알아서 한다. 

그래서 스트림은 고수준이다. 

스트림 현재 상태는 FILE 구조체에 기억된다. 이 구조체는 stdio.h에 정의되어 있다. 

구조체에는 스트림이 내부적으로 사용하는 버퍼, 버퍼 크기와 현재 위치, 액세스하고 있는 파일 이름 등이 저장된다.

파일 입출력 함수가 구조체 내용을 참조하여 동작한다. 

우리가 할 건 파일 입출력 전 구조체 포인터를 선언하고 입출력 함수에게 넘겨주면 된다. 

 

파일 열기

파일을 연다는 건 파일 입출력을 하기 위해 준비한다는 뜻이다. 

스트림 입출력을 위해서 파일 데이터를 잠시 저장하는 내부 버퍼가 필요하고 파일 현재 위치를 초기화해야 하는데,

이런 준비를 하는 과정이다. 

FILE *fopen(const char *filename, const char *mode);

이 함수는 파일 액세스를 하기 위한 준비를 하는데 이 정보를 가지는 FILE형 구조체를 생성하고 포인터를 리턴한다. 

이 포인터를 받아서 입출력 함수에 전달한다. 

 

파일을 다 사용하고 닫아야 하는데 버퍼에 남아있는 데이터를 파일로 완전히 출력(flush)하고 파일 입출력을 위해 내부적으로 생성한 FILE구조체를 해제한다. 

int fclose(FILE *stream);

 

파일 액세스

파일을 열고 파일 안 내용을 읽고 쓴다. 

모든 파일 입출력 함수는 대상 스트림을 전달하기 위해 FILE형 구조체 포인터를 인수로 얻는 공통점이 있다. 

 

임의 접근 

스트림은 다음 입출력할 파일 위치를 항상 기억하고 있다. 

이 위치를 FP(File Position)이라고 한다. 

최초 파일을 열 때 FP는 선두를 가리키고 있으며 스트림에서 내용을 읽거나 쓸 때 FP는 액세스한 만큼 자동으로 뒤로 이동한다. 이런 식으로 파일 처음부터 뒤로 순서대로 접근하는걸 순차 접근(Sequential Access)라고 한다. 

 

기정의 스트림

고수준 입출력 함수들은 스트림 대상으로 입출력을 수행한다. 

스트림은 파일 뿐만 아니라 키보드나 모니터처럼 바이트를 연속적으로 입출력하는 물리 장치까지 포괄하는 개념이다. 

고수준 입출력 함수로 이런 장치를 다룰 수 있다.

키보드나 화면을 스트림으로 관리할 때는 미리 정의되어 있는 표준 스트림을 사용한다. 

이 스트림은 별도로 오픈할 필요가 없고 항상 열려있으며 다 사용하고 닫을 필요 없다. 

 

실시간으로 입력받는 프로그램 경우 버퍼에 아직 읽지 않은 문자가 남아 있다면,

입력 대기를 하지 않고 버퍼에 있는 문자를 바로 읽어 버린다.

따라서 버퍼에 남아있는 불필요한 텍스트를 지우고 다시 입력 받아야 한다. 

 

버퍼는 원래 운영체제가 관리한다. 버퍼가 가득 차거나 스트림을 닫을 때 백그라운드에서 비동기적으로 비워진다. 

프로그램은 버퍼 관리를 신경쓰지 않아도 되지만 당장 사용해야 한다면 버퍼를 즉시 비워야 한다. 

플러쉬란 버퍼에 남아 있는 데이터를 비운다는 뜻이다. 

출력용이면 출력 스트림으로 완전히 보내고 입력용이면 버퍼에 남아 있는 데이터를 삭제한다. 

 

 

 

 

'컴퓨터공학 > C, C++' 카테고리의 다른 글

C,C++> 클래스  (0) 2022.08.04
C,C++> 기타 내용  (0) 2022.08.03
C,C++> 함수 고급  (0) 2022.07.27
C,C++> 포인터 고급  (0) 2022.07.25
C,C++> 구조체  (0) 2022.07.21