파일 입출력 [Windows System Programming]

다루는 내용

Windows System에서 제공하는 기본적인 파일 입출력 함수는 다음과 같습니다.

직관적으로 무엇을 하는 함수인지 알 수 있을 것입니다.

여기에서는 이들 함수의 인자들에 관하여 살펴보기로 할게요.

1. CreateFile
2. CloseHandle
3. WriteFile
4. ReadFile

설명에 사용할 코드

다음의 소스 코드는 정수(int 형식) 데이터를 파일에 기록하는 Save 함수와 파일에서 로딩하여 출력하는 Load 함수로 구성합니다.

콘솔 응용 프로그램 형태로 만들었으며 진입점(main) 함수에서는 Save 함수와 Load 함수를 순차적으로 호출하는 아주 단순한 코드입니다.

정상적으로 파일에 기록하고 로딩하였다면 Save 함수에서 기록한 32를 로딩하여 출력할 것입니다.

#include <Windows.h>
#include <stdio.h>
void Save()
{
	HANDLE hFile = CreateFile(TEXT("data.txt"), GENERIC_WRITE,
		0, 0,
		CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		printf("파일 열기 실패\n");
	}
	else
	{
		int data = 32;

		WriteFile(hFile, &data, sizeof(int), 0, 0);
		CloseHandle(hFile);
	}
}
void Load()
{
	HANDLE hFile = CreateFile(TEXT("data.txt"), GENERIC_READ,
		0, 0,
		OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		printf("파일 열기 실패\n");
	}
	else
	{

		int data = 0;

		ReadFile(hFile, &data, sizeof(int), 0, 0);
		printf("%d\n", data);
		CloseHandle(hFile);
	}
}
int main()
{
	Save();
	Load();

	return 0;
}

실행 결과

32

1. CreateFile

함수 이름을 보면 알 수 있듯이 파일을 생성할 때 사용하는 함수입니다.

CreateFile 함수는 파일을 생성할 때와 이미 생성한 파일을 열 때 사용합니다.

여기에서는 기본적인 내용만 소개합니다. 보다 자세한 내용은 msdn 에서확인하세요.

HANDLE
WINAPI
CreateFileW(
    LPCWSTR lpFileName,
    DWORD dwDesiredAccess,
    DWORD dwShareMode,
    LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    DWORD dwCreationDisposition,
    DWORD dwFlagsAndAttributes,
    HANDLE hTemplateFile
      );                                          msdn바로가기

반환 값

성공하면 열린 핸들을 반환합니다.

실패할 때 INVALID_HANDLE_VALUE를 반환합니다.

#define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)

LPCWSTR lpFileName

생성 혹은 열고자하는 파일 이름입니다.

DWORD dwDesiredAccess

액세스 권한입니다.

읽기 모드일 때는 GENERIC_READ, 쓰기 모드일 때는 GENERIC_WRITE입니다.

읽기 쓰기를 모두 하고자 할 때는 GENERIC_READ|GENERIC_WRITE를 전달합니다.

#define GENERIC_READ                     (0x80000000L)
#define GENERIC_WRITE                    (0x40000000L)
#define GENERIC_EXECUTE                  (0x20000000L)
#define GENERIC_ALL                      (0x10000000L)

DWORD dwShareMode

공유 모드입니다.

다른 프로세스에서 작업을 할 수 있게 허용할 수 있습니다.

보통 파이프와 같은 IPC(Inter Process Communication) 채널을 사용할 때 설정합니다.

#define FILE_SHARE_READ                 0x00000001  
#define FILE_SHARE_WRITE                0x00000002  
#define FILE_SHARE_DELETE               0x00000004  

LPSECURITY_ATTRIBUTES lpSecurityAttributes

보안 설명자입니다.

NULL을 전달하면 기본 보안 설명자를 사용합니다.

DWORD dwCreationDisposition

생성 성향입니다.

CREATE_NEW는 새 파일을 만들 때 사용합니다. 만약 파일이 있으면 실패합니다.

CREATE_ALWAYS는 언제나 새 파일을 만듭니다. 만약 파일이 있으면 기존 파일에 덮어씁니다.

OPEN_EXISTING은 파일이 있을 때만 엽니다. 파일이 없으면 실패합니다.

OPEN_ALWAYS는 항상 파일을 엽니다. 파일이 없으면 새로 만듭니다.

TRUNCATE_EXISTING은 파일이 있을 때 파일을 열고 크기를 0바이트로 자릅니다. 파일이 없으면 실패합니다.

#define CREATE_NEW          1
#define CREATE_ALWAYS       2
#define OPEN_EXISTING       3
#define OPEN_ALWAYS         4
#define TRUNCATE_EXISTING   5

DWORD dwFlagsAndAttributes

파일 특성 및 플래그입니다.

#define FILE_ATTRIBUTE_READONLY             0x00000001  
#define FILE_ATTRIBUTE_HIDDEN               0x00000002  
#define FILE_ATTRIBUTE_SYSTEM               0x00000004  
#define FILE_ATTRIBUTE_DIRECTORY            0x00000010  
#define FILE_ATTRIBUTE_ARCHIVE              0x00000020  
#define FILE_ATTRIBUTE_DEVICE               0x00000040  
#define FILE_ATTRIBUTE_NORMAL               0x00000080  
#define FILE_ATTRIBUTE_TEMPORARY            0x00000100  
#define FILE_ATTRIBUTE_SPARSE_FILE          0x00000200  
#define FILE_ATTRIBUTE_REPARSE_POINT        0x00000400  
#define FILE_ATTRIBUTE_COMPRESSED           0x00000800  
#define FILE_ATTRIBUTE_OFFLINE              0x00001000  
#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED  0x00002000  
#define FILE_ATTRIBUTE_ENCRYPTED            0x00004000  
#define FILE_ATTRIBUTE_INTEGRITY_STREAM     0x00008000  
#define FILE_ATTRIBUTE_VIRTUAL              0x00010000  
#define FILE_ATTRIBUTE_NO_SCRUB_DATA        0x00020000  
#define FILE_ATTRIBUTE_EA                   0x00040000  
#define FILE_ATTRIBUTE_PINNED               0x00080000  
#define FILE_ATTRIBUTE_UNPINNED             0x00100000  
#define FILE_ATTRIBUTE_RECALL_ON_OPEN       0x00040000  
#define FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS 0x00400000 

HANDLE hTemplateFile

템플릿 파일 핸들입니다.

기존 파일을 열 때 이 매개 변수는 무시하며 NULL을 사용할 수 있습니다.

2. CloseHandle

열린 커널 개체의 핸들을 닫습니다.

커널 개체로는 파일 개체, 파일 매핑 개체, 프로세스 개체, 스레드 개체 등이 있습니다.

자세한 사항은 msdn을 참고하세요.

BOOL
WINAPI
CloseHandle(
    HANDLE hObject
    );                                               msdn바로가기

반환 값

성공하면 0이 아닌 값을 반환합니다.

실패하면 0을 반환합니다.

HANDLE hObject

닫을 커널 개체 핸들입니다.

3. WriteFile

파일에 쓰기 함수입니다.

BOOL
WINAPI
WriteFile(
    HANDLE hFile,
    LPCVOID lpBuffer,
    DWORD nNumberOfBytesToWrite,
    LPDWORD lpNumberOfBytesWritten,
    LPOVERLAPPED lpOverlapped
    );                                          msdn바로가기

반환 값

성공하면 0이 아닌 값입니다.

실패하거나 0입니다.

비동기적으로 호출로 완료할 때도 0을 반환합니다.

HANDLE hFile

쓰기 작업을 할 파일 개체 핸들입니다.

LPCVOID lpBuffer

파일에 쓸 데이터가 있는 메모리 주소입니다.

DWORD nNumberOfBytesToWrite

쓰기 작업할 바이트 수입니다.

LPDWORD lpNumberOfBytesWritten

함수 내부에서 쓰기 작업을 완료한 바이트 수를 설정하기 위한 메모리 주소입니다.

비동기 작업일 때는 NULL을 사용하세요.

LPOVERLAPPED lpOverlapped

OVERLAPPED 구조체 변수의 메모리 주소입니다.

비동기 작업 요청할 때 사용합니다.

*non-blocking 작업이라고 얘기하는 것이 좀 더 타당할 수 있습니다.*

4. ReadFile

파일의 내용을 읽어오는 함수입니다.

BOOL
WINAPI
ReadFile(
     HANDLE hFile,
     LPVOID lpBuffer,
     DWORD nNumberOfBytesToRead,
     LPDWORD lpNumberOfBytesRead,
     LPOVERLAPPED lpOverlapped
    );

반환 값

성공하면 0이 아닌 값입니다.

실패하면 0입니다.

비동기 호출로 완료할 때도 0을 반환합니다.

HANDLE hFile

데이터를 읽어올 파일 개체 핸들입니다.

LPVOID lpBuffer

데이터를 읽어올 메모리 주소입니다.

DWORD nNumberOfBytesToRead

읽어올 데이터 바이트 수입니다.

LPDWORD lpNumberOfBytesRead

함수 내부에서 실제 읽어온 바이트 수를 설정하기 위한 메모리 주소입니다.

비동기 작업일 때는 NULL을 사용하세요.

LPOVERLAPPED lpOverlapped

OVERLAPPED 구조체 변수의 메모리 주소입니다.

비동기 작업 요청할 때 사용합니다.

*non-blocking 작업이라고 얘기하는 것이 좀 더 타당할 수 있습니다.*