C++17에서, 경로와 디렉터리, 확장자 등에 관련된 연산을 하는 C++ 표준 라이브러리가 추가됐다. boost API에 있는 기능이었지만, 사용법은 약간 다른 것 같다(boost API를 써 본 적이 없어서 확답을 못 하겠다).
namespace std::experimental::filesystem::v1 에 정의되어 있으며(#include <experimental/filesystem>), C++ 표준 라이브러리와 같이 사용하면 굉장히 편하게 사용이 가능하다.
장점 :
- 파일 경로를 저장하기 위한 path
클래스를 지원한다.
path 클래스의 멤버는 문자열과 경로 설정을 위한 기능을 제공한다.
path 클래스를 사용하여 간단하게 확장자를 확인하고 교체할 수 있다. - path
클래스에서 UNICODE와 MULTIBYTE 모두 지원한다. 이것은 std::wstring과 std::string
같이 문자 집합에 따라 여러 개의 정의가 돼 있는 것이 아니라, 하나의 filesystem 클래스에서 여러 문자 집합으로의 변환을 지원한다는 뜻이다.
즉, 문자집합을 변경할 때마다 클래스를 변경할 필요가 없다. - std::wstring, std::string, char, wchar_t 어떤 타입을 인자로 받아도 상관없다.
2번과 이어지는 장점. - 플랫폼 독립적이다.
- 정확히는 표준을 지원하면 동일한 코드 사용 가능. 표준을 써야하는 이유.
- 파일 복사, 디렉토리 생성, 파일/디렉토리 제거, 현재 디렉토리, 임시 디렉토리 등을 확인하는 함수를 제공한다.
이제부터 어떻게 사용하는지 확인해보자.
※ 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에서 잘 설명해준다!
'프로그래밍 > C++' 카테고리의 다른 글
[C++] invoke 함수의 동작원리를 통해 설명하는 템플릿 부분 특수화와 SFINAE (0) | 2016.08.25 |
---|---|
[C++11] 균일 초기화(중괄호 초기화) (0) | 2016.07.13 |
[C++11] 가변인자 탬플릿(Variadic Template) (0) | 2016.07.13 |
[C++11] enum class (0) | 2016.07.13 |