bool create_bob_txt() { // current directory 를 구한다. wchar_t *buf = NULL; uint32_t buflen = 0; buflen = GetCurrentDirectoryW(buflen, buf); if (0 == buflen) { print("err, GetCurrentDirectoryW() failed. gle = 0x%08x", GetLastError()); return false; } buf = (PWSTR)malloc(sizeof(WCHAR) * buflen); if (0 == GetCurrentDirectoryW(buflen, buf)) { print("err, GetCurrentDirectoryW() failed. gle = 0x%08x", GetLastError()); free(buf); return false; } wchar_t file_name[260]; // bob1에서 생성한 파일을 읽을 준비. if (!SUCCEEDED(StringCbPrintfW( file_name, sizeof(file_name), L"%ws\\bob2.txt", buf))) { print("err, can not create file name"); free(buf); return false; } free(buf); buf = NULL; HANDLE file_handle = CreateFileW( // 메모리에 매핑할 파일의 핸들을 얻는다. 실패 시 INVALID_HANDLE_VALUE를 반환 (LPCWSTR)file_name, GENERIC_READ, NULL, NULL, OPEN_EXISTING, //기존 파일 FILE_ATTRIBUTE_NORMAL, NULL ); if (INVALID_HANDLE_VALUE == file_handle) { print("err, CreateFile(%ws) failed, gle = %u", file_name, GetLastError()); return false; } LARGE_INTEGER fileSize; if (TRUE != GetFileSizeEx(file_handle, &fileSize)) { // 매핑할 파일의 전체 크기를 구한다. print("err, GetFileSizeEx(%ws) failed, gle = %u", file_name, GetLastError()); CloseHandle(file_handle); return false; } _ASSERTE(fileSize.HighPart == 0); // 식을 계산하고 결과가 false 일때, 진단 메시지를 출력하고 프로그램을 중단 /* assert 매크로는 일반적으로 프로그램이 올바르게 작동하지 않을때 false 로 계산하기 위해 expression 인수를 구현함으로써 프로그램을 개발하는 동안 논리적인 오류들을 식별하기 위해 사용된다. 디버깅이 완전히 끝나면, NDEBUG 식별자를 정의하여 소스 파일을 수정하지 않고 어썰션 검사를 끌 수 있다. */ if (fileSize.HighPart > 0) { print("file size = %I64d (over 4GB) can not handle. use FileIoHelperClass", fileSize.QuadPart); CloseHandle(file_handle); return false; } DWORD file_size = (DWORD)fileSize.QuadPart; /* 앞서 CreateFile()을 호출한 이유는 파일 매핑을 수행할 파일의 물리 저장소를 운영체제에게 알려주기 위해. 매핑할 파일을 대상으로 파일 매핑 오브젝트를 생성한다. 지정 파일을 파일 매핑 오브젝트와 연결하며, => reserve 파일 매핑 오브젝트를 위한 충분한 물리 저장소가 존재한다는 것을 확인시키는 작업. 실패시 NULL 반환 */ HANDLE file_map = CreateFileMapping( file_handle, NULL, PAGE_READONLY, 0, 0, NULL ); if (NULL == file_map) { print("err, CreateFileMapping(%ws) failed, gle = %u", file_name, GetLastError()); CloseHandle(file_handle); return false; } // PCHAR : A pointer to a CHAR. This type is declared in WinNT.h as follows : typedef CHAR *PCHAR PCHAR file_view = (PCHAR)MapViewOfFile( file_map, FILE_MAP_READ, 0, 0, 0 ); if (file_view == NULL) { print("err, MapViewOfFile(%ws) failed, gle = %u", file_name, GetLastError()); CloseHandle(file_map); CloseHandle(file_handle); return false; } // UTF-8 -> UTF-16(UCS-2 지원) wchar_t *convchar5 = Utf8MbsToWcs(file_view); _wsetlocale(LC_ALL, L"korean"); wprintf(L"%s\n", convchar5); // 뷰로부터 읽은 데이터를 콘솔에 출력. UnmapViewOfFile(file_view); // 프로세스의 주소 공간 내의 특정 영역에 매핑된 데이터 파일을 더 이상 유지하지 않음. 뷰를 해제. CloseHandle(file_map); CloseHandle(file_handle); return true; }
bool read_bob2_txt() { wchar_t *buf = getCurrentDir(); wchar_t file_name[260]; if (!SUCCEEDED(StringCbPrintfW( // safe하도록 모든 boundary check를 다 해주는 API file_name, sizeof(file_name), L"%ws\\bob2.txt", buf))) { print("err, cannot create file name"); free(buf); return false; } free(buf); buf = NULL; HANDLE file_handle = CreateFileW( file_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); char contents[1024]; DWORD nBytesRead; memset(contents, NULL, sizeof(contents) / sizeof(char)); ReadFile(file_handle, contents, sizeof(contents) / sizeof(char), &nBytesRead, NULL); /* [1] Using ReadFile() */ // console은 ANSI에 맞춰져있어서 UTF8 -> ANSI 필요 wchar_t *ucs2_contents = Utf8MbsToWcs(contents + 3); // do not convert BOM int outLen = WideCharToMultiByte(CP_ACP, 0, ucs2_contents, -1, NULL, 0, NULL, NULL); memset(contents, NULL, sizeof(contents) / sizeof(char)); if (0 == WideCharToMultiByte(CP_ACP, 0, ucs2_contents, -1, contents, outLen, NULL, NULL)) { print("err, UCS2 to ANSI failed."); free(ucs2_contents); CloseHandle(file_handle); } printf("[1] %s\n", contents); free(ucs2_contents); /* [2] Using memory-mapped I/O */ HANDLE file_map = CreateFileMapping( file_handle, NULL, PAGE_READONLY, 0, 0, NULL ); if (NULL == file_map) { print("err, CreateFileMapping(%ws) failed, gle = %u", file_name, GetLastError()); CloseHandle(file_handle); return false; } PCHAR file_view = (PCHAR)MapViewOfFile( file_map, FILE_MAP_READ, 0, 0, 0 ); if (NULL == file_view) { print("err, MapViewOfFile(%ws) failed, gle = %u", file_name, GetLastError()); CloseHandle(file_map); CloseHandle(file_handle); return false; } ucs2_contents = Utf8MbsToWcs(file_view + 3); outLen = WideCharToMultiByte(CP_ACP, 0, ucs2_contents, -1, NULL, 0, NULL, NULL); memset(contents, NULL, sizeof(contents) / sizeof(char)); if (0 == WideCharToMultiByte(CP_ACP, 0, ucs2_contents, -1, contents, outLen, NULL, NULL)) { print("err, UCS2 to ANSI failed."); free(ucs2_contents); CloseHandle(file_handle); } printf("[2] %s\n", contents); free(ucs2_contents); CloseHandle(file_handle); return true; }