Created
October 13, 2023 11:27
-
-
Save qycyfjy/d2e8aa8245ebb46f3396e4fc69f85a4e to your computer and use it in GitHub Desktop.
MSVC下使用<filesystem>
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
主旨就是: | |
1.源文件使用UTF-8编码 | |
2.编译选项加上/utf-8 | |
3.涉及到路径的操作统统使用w系列字符串: 使用wstring而不是string, 使用wstringstream而不是stringstream等等, 在使用字符串字面量时使用L""前缀, 类型为const wchar_t* | |
4.可以在构造一个path后使用make_preferred()把间隔符统一了, 防止'/', '\\'混杂不和谐 | |
注意第三条, 是涉及路径, 不是涉及文件, 一个典型的顺序是: | |
1. 使用wstring类型的文件路径(如果来源不是wstring/wchar_t要分情况把ANSI(一般是从控制台获得的输入)或者UTF-8转为wstring的UTF-16)构造一个path | |
2. 使用这个path构造一个fstream | |
3. 按文件内容是binary还是各种编码的文本去处理, 很多时候文本文件都是UTF-8编码所以按char进行读写, binary也要按char读写, 之后就是一水的char[]/string了 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ReSharper disable CppClangTidyClangDiagnosticInvalidSourceEncoding | |
// ReSharper disable StringLiteralTypo | |
#include <Windows.h> // WideCharToMultiByte用于把宽字符UTF-16转为UTF-8 SetConsoleOutputCP控制控制台输出代码页为UTF-8 | |
#undef min | |
#undef max | |
#include <iostream> | |
#include <iomanip> | |
#include <sstream> | |
#include <filesystem> | |
#include <fstream> | |
using namespace std; | |
using namespace std::filesystem; | |
string wide2_utf8(const wstring_view& wstr) | |
{ | |
const int count = WideCharToMultiByte(CP_UTF8, 0, wstr.data(), static_cast<int>(wstr.length()), nullptr, 0, nullptr, nullptr); | |
std::string str(count, 0); | |
WideCharToMultiByte(CP_UTF8, 0, wstr.data(), -1, str.data(), count, nullptr, nullptr); | |
return str; | |
} | |
wstring file_detail(const path& path_of_file) | |
{ | |
wostringstream wos; | |
int i = 0; | |
wos << L"\t当前文件组成: " << path_of_file << endl; | |
for (auto iter = path_of_file.begin(); iter != path_of_file.end(); ++iter) | |
{ | |
wos << L"\t\t第" << i++ << L"部分: " << *iter << endl; | |
} | |
wos << L"\t根目录名 = " << path_of_file.root_name() << endl | |
<< L"\t根目录路径 = " << path_of_file.root_path() << endl | |
<< L"\t相对路径 = " << path_of_file.relative_path() << endl | |
<< L"\t父路径 = " << path_of_file.parent_path() << endl | |
<< L"\t文件名 = " << path_of_file.filename() << endl | |
<< L"\t无扩展名 = " << path_of_file.stem() << endl | |
<< L"\t拓展名 = " << path_of_file.extension() << endl; | |
return wos.str(); | |
} | |
int main() | |
{ | |
::SetConsoleOutputCP(65001); | |
path sample_file(L"D:/WeGameApps/地下城与勇士:创新世纪/地下城与勇士:创新世纪"); | |
sample_file.make_preferred(); | |
const path summary_path = sample_file.parent_path() / L"总结.txt"; | |
if(exists(summary_path)) | |
{ | |
remove(summary_path); | |
} | |
auto directory_iter = directory_iterator(sample_file.parent_path()); | |
int file_count = 0; | |
int dir_count = 0; | |
bool detail = false; | |
wostringstream wos; | |
for (; directory_iter != directory_iterator(); ++directory_iter) | |
{ | |
if (directory_iter->is_regular_file()) | |
{ | |
++file_count; | |
wos << L"<R>"; | |
detail = true; | |
} | |
else | |
{ | |
++dir_count; | |
wos << L"<D>"; | |
detail = false; | |
} | |
wos << directory_iter->path() << endl; | |
if (detail) | |
{ | |
wos << file_detail(directory_iter->path()); | |
} | |
} | |
stringstream out; | |
out << "一共" << file_count << "个普通文件, " << dir_count << "个文件夹" << endl; | |
out << wide2_utf8(wos.str()) << endl; | |
if (ofstream summary(summary_path, ios_base::trunc); summary.is_open()) | |
{ | |
summary << out.rdbuf(); | |
cout << "完成, 请查看" << wide2_utf8(summary_path.c_str()) << endl; | |
} | |
else | |
{ | |
cout << "无法创建文件, 打印到控制台" << endl; | |
cout << out.rdbuf(); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment