본문 바로가기

프로그래밍/C++

[C++17] filesystem

C++17에서, 경로와 디렉터리, 확장자 등에 관련된 연산을 하는 C++ 표준 라이브러리가 추가됐다. boost API 있는 기능이었지만, 사용법은 약간 다른 같다(boost API 적이 없어서 확답을 하겠다).

 

namespace std::experimental::filesystem::v1 정의되어 있으며(#include <experimental/filesystem>), C++ 표준 라이브러리와 같이 사용하면 굉장히 편하게 사용이 가능하다.

 

장점 :

  1. 파일 경로를 저장하기 위한 path 클래스를 지원한다.
    path 클래스의 멤버는 문자열과 경로 설정을 위한 기능을 제공한다.
    path 클래스를 사용하여 간단하게 확장자를 확인하고 교체할 있다.
  2. path 클래스에서 UNICODE MULTIBYTE 모두 지원한다. 이것은 std::wstring std::string 같이 문자 집합에 따라 여러 개의 정의가 있는 것이 아니라, 하나의 filesystem 클래스에서 여러 문자 집합으로의 변환을 지원한다는 뜻이다.
    , 문자집합을 변경할 때마다 클래스를 변경할 필요가 없다.
  3. std::wstring, std::string, char, wchar_t  어떤 타입을 인자로 받아도 상관없다.
    2
    번과 이어지는 장점.
  4. 플랫폼 독립적이다.
    • 정확히는 표준을 지원하면 동일한 코드 사용 가능. 표준을 써야하는 이유.
  1. 파일 복사, 디렉토리 생성, 파일/디렉토리 제거, 현재 디렉토리, 임시 디렉토리 등을 확인하는 함수를 제공한다.

 

 

 

이제부터 어떻게 사용하는지 확인해보자.

std::experimental::filesystem::v1 붙이기에는 무리가 있으므로 생략한다.

 

기본적으로 filesystem 정의된 대부분의 함수는 path 클래스를 사용한다.

path 클래스를 사용하는 방법은 매우 간단하다. std::string 동일하게 사용하면 된다.

path 클래스는 문자 배열과 표준 string 클래스를 통한 생성을 지원한다.

 

path myPath = "C:/Lusain/game.txt";

 

여기서 .txt .exe 변경하고 싶으면 다음 멤버함수를 호출한다.

 

myPath.replace_extension(".exe");

 

또는, game 아닌 LusGame으로 변경하고 싶으면 다음 멤버함수를 호출한다.

 

myPath.replace_filename("LusGame.exe");

replace_filename으로 파일명을 바꾸면 확장자까지 바뀌므로 주의.

 

 외부에서 읽은 문자열로 만든 path 클래스가 원하는 확장자를 가졌는지 확인하는 방법은 다음과 같다.

 

if (myPath.extension() == ".txt") // TODO: ~~

 

 

 

리소스를 관리할 , 종류에 따라 여러 디렉토리에 접근해야 한다.
/
연산자가 오버로딩 되어 있기 때문에, 다음과 같이 작성할 있다.

 

// MyData/Image 저장하려고 .

string data { "myImage.png" };

string DirData { "MyData" };

string DirImage { "Image" };

 

path SavePath = DirData / DirImage / data;

 

 

 

만약 path 클래스의 데이터를 문자열로 가져오고 싶으면 멤버함수를 이용하면 된다.

.c_str()

.generic_string()

.generic_wstring()

.generic_u8string()

.generic_u16string()

.generic_u32string()

.string()

.wstring()

.u8string()

.u16string()

.u32string()

 

여기서 generic_ 붙은 멤버함수는 백슬래쉬(\) 경로 구분자를 슬래쉬(/) 바꿔 반환한다.

 

 

 

filesystem 파일 또는 디렉토리의 생성, 삭제, 복사, 이름 바꾸기, 이동, 존재 여부 등을 전역 함수로 지원한다. 자세한 것은 MSDN 참고.

 

예시를 들어보자.

파일인지 확인

is_regular_file(path)

디렉토리인지 확인

is_directory(path)

존재하는지 확인

exists(path)

파일명 변경

rename(path, path)

파일 삭제

remove(path)

파일 또는 디렉토리 복사

copy_file(path, path, copy_options)

디렉토리 생성

create_directory(path)

 

 

 

path 디렉토리라면, 이를 인자로 directory_iterator 만들어 해당 디렉토리의 파일을 순회할 있다. 이를 통해 특정 디렉토리의 파일을 모두 얻어오는 함수를 만들 있다. 맨 마지막 인자로 하위 디렉토리를 재귀적으로 추가할 것인지 설정할 수 있다.

 

 

bool GetFiles(vector<path>& v, const path& Dir, bool bSearchSubDirectories = true)

{

if (!is_directory(Dir)) return false;

for (const auto& entry : directory_iterator { Dir })

{

if (is_regular_file(entry.status()))

v.push_back(entry.path());

else if (is_directory(entry.status()))

GetFiles(v, entry.path(), bSearchSubDirectories);

}

return true;

}

 

더욱 자세한 것은 MSDN 참고하자. Modern C++부터는 MSDN에서 설명해준다!