ぬの部屋(仮)
nu-no-he-ya
  •  123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
         12
    3456789
    10111213141516
    17181920212223
    2425262728  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
       1234
    567891011
    12131415161718
    19202122232425
    26272829   
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28      
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
    1234567
    891011121314
    15161718192021
    22232425262728
           
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
         12
    3456789
    10111213141516
    17181920212223
    242526272829 
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
        123
    45678910
    11121314151617
    18192021222324
    25262728   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    15161718192021
    293031    
           
         12
    3456789
    10111213141516
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
          1
    2345678
    9101112131415
    16171819202122
    232425262728 
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
  • ディレクトリツリーを作成

    以前にもstd::filesystemでディレクトリツリーを作成するコードをいつもより少しだけ真面目に書いた。

    #include <iostream>
    
    #include <vector>
    #include <string>
    #include <filesystem>
    
    // SetConsoleOutputCP のために必要
    #include <windows.h>
    
    enum class FileType {
        Ignore,
        Directory,
        File
    };
    enum class ExceptionType {
        Success,
        // 子要素の収集に失敗(イテレータ取得に失敗)
        // あるノードにこのエラーがついていた場合、そのノードの子要素は取得できていない
        ChildrenIteratorError,
        NodeTypeError,
        NodeNameError,
        NotInit,
        Other,
    };
    
    using PathString = std::u8string;
    
    inline PathString ToFilenameString(const std::filesystem::path& path) {
    
        std::filesystem::path tmp;
        if (path.filename().empty()) {
            tmp = path.parent_path();  // 末尾がスラッシュなら親ディレクトリを取得
        }
        else {
            tmp = path; // 末尾がスラッシュでないならそのまま
        }
    
        PathString fname = tmp.filename().u8string();
        return fname;
    
    }
    
    struct ErrorData {
        ExceptionType type;
        std::string message;
        std::filesystem::path path;
    public:
        ErrorData() : type(ExceptionType::Success) {}
        ErrorData(ExceptionType type, const std::string& message) : type(type), message(message) {}
    };
    
    
    // 自作の例外クラス
    class FileSystemTreeException : public std::exception {
    private:
        std::string message;
        ErrorData error_data;
    public:
        explicit FileSystemTreeException(const std::string& msg, const std::filesystem::path& _path_, const ExceptionType type) :
            message(msg) {
            error_data.type = type;
            error_data.message = msg;
            error_data.path = _path_;
        }
    
        const char* what() const noexcept override {
            return message.c_str();
        }
    
        const ErrorData& getErrorData() const {
            return error_data;
        }
    };
    

    // ノードの子ノード配列を扱うクラス
    // FileSystemTreeで子ノードの読み込みに失敗した場合はerror_dataに内容が入っている
    class
    ChildrenNodes { std::vector<std::unique_ptr<class FileSystemTree>> children; ErrorData error_data; public: ChildrenNodes() {} ChildrenNodes& operator=(std::vector<std::unique_ptr<class FileSystemTree>>&& other) noexcept { children = std::move(other); return *this; } void push_back(std::unique_ptr<class FileSystemTree>&& node) { children.push_back(std::move(node)); } bool isValid()const { return error_data.type == ExceptionType::Success; } void setError(const ErrorData& err) { error_data = err; } const ErrorData& getError() const { return error_data; } std::vector<std::unique_ptr<class FileSystemTree>>::const_iterator cbegin() const { return children.cbegin(); } std::vector<std::unique_ptr<class FileSystemTree>>::const_iterator cend() const { return children.cend(); } std::vector<std::unique_ptr<class FileSystemTree>>::iterator begin() { return children.begin(); } std::vector<std::unique_ptr<class FileSystemTree>>::iterator end() { return children.end(); } std::vector<std::unique_ptr<class FileSystemTree>>::const_iterator begin() const { return children.cbegin(); } std::vector<std::unique_ptr<class FileSystemTree>>::const_iterator end() const { return children.cend(); } };

    // ディレクトリツリーのクラス
    class
    FileSystemTree { PathString name; // ファイル名・ディレクトリ名 FileType type; // ファイルかディレクトリか ErrorData error_data; // このノードのエラー情報 ChildrenNodes children; // 子ノード一覧 ChildrenNodes error_children; // エラーが発生した子ノード一覧 public: FileSystemTree(const PathString& name, const FileType type) : name(name), type(type) {} FileSystemTree() :type(FileType::Ignore) {}; FileSystemTree(const ErrorData& err) : error_data(err), type(FileType::Ignore) {}
    // このノードについて、子ノードの読み込みに失敗した場合に設定 // 注意:子ノード一つ一つではなく、イテレータの取得の段階で失敗したような場合に使用 void setChildrenError(const ExceptionType type, const std::string str) { children.setError(ErrorData(type, str)); }
    // このノードの子ノード一覧を設定
    // アクセスできない子を見つけた場合はerrorchildrenに入れて渡す
    void setChildren( std::vector<std::unique_ptr<FileSystemTree>>&& children, std::vector<std::unique_ptr<FileSystemTree>>&& errorchildren) { this->children = std::move(children); this->error_children = std::move(errorchildren); } const ChildrenNodes& getChildren()const { return children; }// 子ノード一覧へアクセス void setError(const ErrorData& err) { error_data = err; }// このノードがエラーノードであることを設定(普通コンストラクタで指定可能なので使わない) bool isChildrenValid() const { return children.isValid(); }// 子ノード一覧の生成に成功したかどうか。たとえ要素0でも生成に成功していればtrue ChildrenNodes& getErrorChildren() { return error_children; }// 子ノード一一覧生成時、読み込めなかったときに発生したエラー一覧 const PathString& getName() const { return name; }// ノード名 FileType getType() const { return type; }// ファイルかディレクトリか bool isFailure() const { return error_data.type != ExceptionType::Success; }// このノードがエラーノードであるか const ErrorData& getError() const { return error_data; }// このノードのエラー情報 };

    std::unique_ptr<FileSystemTree> MakeFilesystemNode(const std::filesystem::path& path) {
    
        FileType type;
        PathString name;
        try {
            // ノードの種類を特定
            type = std::filesystem::is_directory(path) ? FileType::Directory : FileType::File;
        }
        catch (const std::exception& e) {
            throw FileSystemTreeException(e.what(), path, ExceptionType::NodeTypeError);
        }
    
        try {
            // ノードの名前を取得
            name = ToFilenameString(path);
        }
        catch (const std::exception& e) {
            throw FileSystemTreeException(e.what(), path, ExceptionType::NodeNameError);
        }
    
        std::unique_ptr<FileSystemTree> the_node = std::make_unique<FileSystemTree>(name, type);
        return the_node;
    }
    

    // ディレクトリツリーを構築する関数
    void buildDirTreeCore(std::unique_ptr<FileSystemTree>& this_directory, const std::filesystem::path& path) {
    
        if (this_directory->getType() == FileType::Directory) {
            // ノードがディレクトリの場合、子ノードを追加
    
            // pathの中身を取得するイテレータを作成
            std::filesystem::directory_iterator dir_itr;
            try {
                dir_itr = std::filesystem::directory_iterator(path);
            }
            catch (const std::filesystem::filesystem_error& e) {
                // 失敗した場合、このディレクトリ内のファイルを取得できないことを意味する
                this_directory->setChildrenError(ExceptionType::ChildrenIteratorError, e.what());
                return;
            }
            catch (const std::exception& e) {
                this_directory->setChildrenError(ExceptionType::Other, e.what());
                return;
            }
    
            std::vector<std::unique_ptr<FileSystemTree>> nowchildren; // this_directoryの子ノード一覧
            std::vector<std::unique_ptr<FileSystemTree>> errors; // エラーが発生した子ノード一覧
    
            // ディレクトリ内の項目を取得して追加
            for (const auto& entry : dir_itr) {
                std::unique_ptr<FileSystemTree> newnode;
    
                try {
                    // 子要素のリストを作成
                    newnode = MakeFilesystemNode(entry.path());
                    nowchildren.emplace_back(std::move(newnode));
                }
                catch (const FileSystemTreeException& e) {
                    // エラーが発生した場合、エラーノードを追加
                    errors.push_back(std::make_unique<FileSystemTree>(e.getErrorData()));
                }
    
            }
    
            for (auto& subdirectory : nowchildren) {
                // ディレクトリのみ、サブディレクトリを再帰的に処理
                if (subdirectory->getType() == FileType::Directory) {
    
                    const std::filesystem::path& subpath = path / subdirectory->getName();
                    buildDirTreeCore(subdirectory, subpath);
                }
            }
            this_directory->setChildren(std::move(nowchildren), std::move(errors));
        }
    }
    

    std::unique_ptr<FileSystemTree> BuildTree(const std::filesystem::path& path) {
        std::unique_ptr<FileSystemTree> this_directory;
        auto entry = path.lexically_normal();
        this_directory = MakeFilesystemNode(entry); // パスからノードを作成
        buildDirTreeCore(this_directory, entry);
        return this_directory;
    }
    
    /////////////////////////////////////////////////////////////////////////////////////
    // ファイルツリーを表示
    void PrintTree(const std::unique_ptr<FileSystemTree>& node, int depth = 0) {
    
    
        auto to_string = [](const FileType type) {
            switch (type) {
            case FileType::Ignore:    return "*";
            case FileType::Directory: return "[DIR] ";
            case FileType::File:      return "[FILE] ";
            }
            return "Unknown";
            };
    
        std::string indent(depth * 2, ' ');
        if (node->isFailure()) {
            std::cout << indent << to_string(node->getType()) << (const char*)node->getName().c_str() << " : " << node->getError().message << "\n";
        }
        else {
            std::cout << indent << to_string(node->getType()) << (const char*)node->getName().c_str() << "\n";
        }
        if (node->isChildrenValid() == false) {
            std::cout << indent << "  ** Children Error: " << node->getChildren().getError().message << "\n";
        }
        else {
            for (const auto& child : node->getChildren()) {
                PrintTree(child, depth + 1);
            }
        }
        for (const auto& error : node->getErrorChildren()) {
            std::cout << indent << "  ** Error: " << error->getError().message << "\n";
        }
    }
    int main()
    {
        // ロケール設定
        std::locale::global(std::locale("ja_JP.UTF-8"));
        std::cerr.imbue(std::locale("ja_JP.UTF-8"));
        std::cout.imbue(std::locale("ja_JP.UTF-8"));
        SetConsoleOutputCP(CP_UTF8);
    
        std::string path = R"(C:\test\myaccess)";
    
        std::unique_ptr<FileSystemTree> root = BuildTree(path);// ファイルパスからツリーを作成
        
        PrintTree(root);
    
    }