2017-09-04 42 views
2

私はブーストtutorialsと同じ例を使用しています。しかし、私のファイル名には番号が付けられているので(1,20,23、..)。コードが文字列の比較に失敗しました(例20 < 7)。 directory_iterationを数値的に比較する方法はありますか?boost :: filesystemを使用してディレクトリのサブフォルダとファイル名を数値でソート

root/ 
    1/ 
    1.bmp 
    2.bmp 
    3.bmp 
    4.bmp 
    ... 
    2/ 
    1.bmp 
    2.bmp 
    3.bmp 
    4.bmp 
    .... 
    3/ 
    1.bmp 
    2.bmp 
    3.bmp 
    4.bmp 
    .... 
+1

次回の桁数が固定されて(使用します使用されているすべての値をファイル名に埋め込みます)、問題はなくなります。たとえば、最大で100個のファイル(0-99)が '01.txt'、' 20.txt'、 '23.txt'などのファイルに名前を付けると期待している場合です。今すぐファイル名の数値を解析し、それを使って並べ替える必要があります。 –

+0

@DanMašekファイルは別のソフトウェアによって自動的に生成されますが、商用ソフトウェアであるため、編集することはできません。私は自分のものと仕事をしなければならない。私はそれぞれ50個以上のサブフォルダを持っていて、1から127までの番号のファイルがあります。自分で名前を変更するのはtidusです。 Thnx – Bob

+1

パスからこれらの数値を取得して比較するカスタムコンパレータを使用します。 –

答えて

2

であるとして、あなたがソート可能にするために、ファイル名の形式を変更することはできませんので、あなたがする必要があります。ここではディレクトリとサブフォルダのレイアウトは、ここで示されたコード

else if (is_directory(p))  // is p a directory? 
     { 
     cout << p << " is a directory containing:\n"; 

     typedef vector<path> vec;    // store paths, 
     vec v;        // so we can sort them later 

     copy(directory_iterator(p), directory_iterator(), back_inserter(v)); 

     sort(v.begin(), v.end());    // **I want to sort this numerically** 

     for (vec::const_iterator it(v.begin()), it_end(v.end()); it != it_end; ++it) 
     { 
      cout << " " << *it << '\n'; 
     } 
     } 

の抜粋ですいくつかの処理を自分で行う - 各ファイル名から数値を解析し、ソートに使用する。

2つのアプローチが思い浮かび上がり、メモリとCPU使用率の間で相殺されます。

アプローチ1:ベクターを移入するとき構文解析ファイル名と数値の

ストア対。

アプローチ2:

比較の際にパスだけを格納して変換を実行します。


コード:ディレクトリの

#include <boost/filesystem/path.hpp> 
#include <boost/filesystem/operations.hpp> 
#include <iostream> 

namespace fs = boost::filesystem; 

int parse_filename(fs::path const& p) 
{ 
    return std::stoi(p.filename().string()); 
} 

void sort_numeric_1(fs::path const& p) 
{ 
    typedef std::pair<fs::path, int> file_entry; 
    typedef std::vector<file_entry> vec; 
    vec v; 

    for (fs::directory_iterator it(p); it != fs::directory_iterator(); ++it) { 
     v.emplace_back(*it, parse_filename(*it)); 
    } 

    std::sort(v.begin(), v.end() 
     , [](file_entry const& a, file_entry const& b) { 
     return a.second < b.second; 
    }); 

    for (vec::const_iterator it(v.begin()), it_end(v.end()); it != it_end; ++it) { 
     std::cout << " " << it->first << '\n'; 
    } 
} 

void sort_numeric_2(fs::path const& p) 
{ 
    typedef std::vector<fs::path> vec; 
    vec v; 

    std::copy(fs::directory_iterator(p), fs::directory_iterator(), back_inserter(v)); 

    std::sort(v.begin(), v.end() 
     , [](fs::path const& a, fs::path const& b) { 
     return std::stoi(a.filename().string()) < std::stoi(b.filename().string()); 
    }); 

    for (vec::const_iterator it(v.begin()), it_end(v.end()); it != it_end; ++it) { 
     std::cout << " " << *it << '\n'; 
    } 
} 

int main() 
{ 
    sort_numeric_1("test"); 
    std::cout <<"\n"; 
    sort_numeric_2("test"); 
} 

内容:

> ls test 
1.txt 10.txt 127.txt 20.txt 23.txt 

出力:

"test\1.txt" 
"test\10.txt" 
"test\20.txt" 
"test\23.txt" 
"test\127.txt" 

"test\1.txt" 
"test\10.txt" 
"test\20.txt" 
"test\23.txt" 
"test\127.txt" 

時間にそれを更新しますあなたが示されてきたandle全体のディレクトリ構造、あなたはこのようなものかもしれない:

  • 最初にすべてのディレクトリを検索し、数値的に
  • それらを並べ替えるに見つからディレクトリ
  • のそれぞれのファイルは、すべてのマージソートしますファイルのソートされたリスト

例:

#include <boost/filesystem/path.hpp> 
#include <boost/filesystem/operations.hpp> 
#include <iostream> 

namespace fs = boost::filesystem; 

typedef std::vector<fs::path> path_vec; 

void sort_numeric(path_vec& v) 
{ 
    std::sort(v.begin(), v.end() 
     , [](fs::path const& a, fs::path const& b) { 
     return std::stoi(a.filename().string()) < std::stoi(b.filename().string()); 
    }); 
} 

path_vec sort_root_dir(fs::path const& p) 
{ 
    path_vec dirs; 

    for (fs::directory_iterator it(p); it != fs::directory_iterator(); ++it) { 
     if (is_directory(*it)) { 
      dirs.emplace_back(*it); 
     } 
    } 

    sort_numeric(dirs); 

    path_vec files; 
    for (path_vec::const_iterator it(dirs.begin()), it_end(dirs.end()); it != it_end; ++it) { 
     path_vec dir_files; 
     std::copy(fs::directory_iterator(*it), fs::directory_iterator(), back_inserter(dir_files)); 
     sort_numeric(dir_files); 
     files.insert(files.end(), dir_files.begin(), dir_files.end()); 
    } 

    return files; 
} 

int main() 
{ 
    path_vec files = sort_root_dir("test"); 

    for (auto const& f : files) { 
     std::cout << f << "\n"; 
    } 
} 
+0

複数のサブフォルダに対して1つのサブフォルダしか持たない場合、これは完璧に機能します。失敗すると、(std :: invalid_argument 'what():stoi)のインスタンスをスローした後に終了します。 – Bob

+0

これは単なるファイルで1つのディレクトリの並べ替えを行う方法の基本的な例です。ネストされたディレクトリを処理するためにいくつかのチェックを追加する必要があります。おそらく、ディレクトリツリーのレイアウトのいくつかの例を示すことができれば(それで私たちは何を期待するのか分かります)、より完全な解決策を得ることができます。 –

+1

私はちょうど質問のレイアウト構造を更新しました – Bob

関連する問題