スポンサーリンク

C++で、複数のディレクトリに格納された連番ファイルを番号ごとに管理する


#include <iostream>
#include <vector>
#include <filesystem>
#include <regex>
#include <unordered_map>

struct PathList {
    std::vector<std::filesystem::path> directories;
    std::vector<std::filesystem::path> files;
};

// 指定したパス内のファイル一覧を取得
PathList
GetFileList(const std::filesystem::path& _path) { PathList result; if (!std::filesystem::exists(_path) || !std::filesystem::is_directory(_path)) { return result; // 存在しない場合は空を返す } for (const auto& entry : std::filesystem::directory_iterator(_path)) { if (entry.is_directory()) { result.directories.push_back(entry.path()); } else if (entry.is_regular_file()) { result.files.push_back(entry.path()); } } return result; }
      

// パスのファイル名からIDを取り出し、pair<size_t, path> の配列で返す
std::vector<std::pair<size_t, std::filesystem::path>>
GetFileIncdies(const std::vector<std::filesystem::path>& pathlist,
    const std::regex& pattern,
    std::vector<std::filesystem::path>* excep)
{
    std::vector<std::pair<size_t, std::filesystem::path>> result;

    for (const auto& p : pathlist) {
        const std::string name = p.filename().string();

        std::smatch m;
        if (std::regex_search(name, m, pattern)) {

            // パターンにマッチしたかどうか
            bool ok = false;

            size_t idx = 0;

            for (size_t i = 1; i < m.size(); ++i) {
                const std::string s = m[i].str();
                if (s.empty()) continue;

                // すべて数字かを判定
                const bool all_digits = std::all_of(s.begin(), s.end(),
                    [](unsigned char c) { return std::isdigit(c) != 0; });

                if (!all_digits) continue;

                try {
                    idx = static_cast<size_t>(std::stoull(s));
                    ok = true;
                    break;
                }
                catch (...) {
                    // stoull 失敗時は次のキャプチャを試す
                }
            }

            if (ok) {
                result.emplace_back(idx, p);
            }
            else if (excep) {
                excep->push_back(p);
            }
        }
        else {
            if (excep) excep->push_back(p);
        }
    }

    // インデックス昇順、同値ならパスの辞書順
    std::sort(result.begin(), result.end(),
        [](const auto& a, const auto& b) {
            if (a.first != b.first) return a.first < b.first;
            return a.second < b.second;
        });

    return result;
}

template<typename Tuple,typename Pair,int Index>
std::unordered_map<size_t, Tuple> CreateDataSetList(std::unordered_map<size_t, Tuple>& datamap,std::vector<Tuple>& datasets, std::vector<Pair>& pairs) {

    for (const auto& p : pairs) {
        size_t idx = p.first;
        const auto& path = p.second;

        auto& tupleitem = datamap[idx];
        std::get<Index>(tupleitem) = path; // Index番目にパスをセット

    }
    return datamap;
}
      
// マップをIDでソートしたものを返す
template<typename Tuple>
std::vector<std::pair<size_t, Tuple>> SortByID(const std::unordered_map<size_t, Tuple>& byidmap) {
    std::vector<std::pair<size_t, Tuple>> sorted;
    sorted.reserve(byidmap.size());

    for (const auto& kv : byidmap) {
        sorted.emplace_back(kv.first, kv.second);
    }

    std::sort(sorted.begin(), sorted.end(),
        [](const auto& lhs, const auto& rhs) {
            return lhs.first < rhs.first; // size_tキーで昇順
        });

    return sorted;
}

using
Tuple = std::tuple<std::filesystem::path, std::filesystem::path, std::filesystem::path>; using Pair = std::pair<size_t, std::filesystem::path>;
// パスとパターンからファイル一覧を作成し、インデックスとパスのペアを返す関数
std::vector<std::pair<size_t, std::filesystem::path> > GetFiles(const std::filesystem::path& path,std::regex pattern){
    PathList fileList = GetFileList(path);

    std::vector<std::pair<size_t, std::filesystem::path> > flist;
    flist = GetFileIncdies(fileList.files, pattern, nullptr);

    return flist;
}
int main()
{
    std::vector< Tuple > dataSetList;

    std::vector<Pair > list_1 = GetFiles("C:\\test\\tmp\\txt", std::regex(R"(新規 テキスト000_(\d+)\.txt)") );
    std::vector<Pair > list_2 = GetFiles("C:\\test\\tmp\\doc", std::regex(R"(doc_000_(\d+)\.doc)") );

    std::unordered_map<size_t, Tuple> byidmap;
    CreateDataSetList<Tuple, Pair, 0>(byidmap, dataSetList, list_1);
    CreateDataSetList<Tuple, Pair, 1>(byidmap, dataSetList, list_2);

    std::vector<std::pair<size_t, Tuple>> sorted = SortByID(byidmap);
    for(const auto& b : sorted) {
        std::cout << "ID: " << b.first << " " << std::get<0>(b.second).filename() << " " << std::get<1>(b.second).filename() << " " << std::get<2>(b.second) << "\n";
    }

}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: