Search code examples
c++boostboost-filesystem

C++ Boost::filesystem::path with unicode characters


I am new to C++, need a little help here. I have three folders - one in English, one in Japanese and one in Russian for test purposes. When I run this little program

#include <windows.h>
#include <string>
#include <iostream>
#include <boost/filesystem.hpp>
#include <boost/locale.hpp>

using namespace boost::filesystem;
using namespace std;

void iterateDirs(const path &dir_path, vector<path> &dir)
{
    if ( exists( dir_path ) )
    {
        directory_iterator end_itr;
        for ( directory_iterator itr(dir_path); itr != end_itr; ++itr ) {
            if ( is_directory(itr->status()) ) {
                cout << *itr << endl;
                dir.push_back(itr->path());
                cout << dir.size() << endl;
            }
        }
    }
}

int main() {
    vector<path> dirs;

    iterateDirs("D:/Test", dirs);
    for (path p : dirs) {
        cout << p << endl;
    }
    return 0;
}

only english letters are recognized. This is how the output looks

D:/Test\lol"
1
"D:/Test\ыюы"
2
"D:/Test\???"
3
"D:/Test\lol"
"D:/Test\ыюы"
"D:/Test\???"

Process finished with exit code 0

It doesnt seem like only cout problem, because when I am trying to do anything (like open these folders in explorer using winapi) with vector items, only english-named folder is recognized by the program code.

I have searched this site and google for solutions and neither of them worked. Tried using wcout wstring wchar_t etc nothing works.

Using mingw w64 4.0 with gcc and clion/cmake on windows 8. Thanks!


Solution

  • Unfortunately unicode output to windows console is not easy task. Most reliable way to do it - is to use _cputws or WriteConsoleW - but these functions write directly to console and streams redirections don't work with them. This program:

    #include <windows.h>
    #include <string>
    #include <iostream>
    #include <boost/filesystem.hpp>
    #include <boost/locale.hpp>
    
    using namespace boost::filesystem;
    using namespace std;
    
    void iterateDirs(const path &dir_path, vector<path> &dir)
    {
        if ( exists( dir_path ) )
        {
            directory_iterator end_itr;
            for ( directory_iterator itr(dir_path); itr != end_itr; ++itr ) {
                if ( is_directory(itr->status()) ) {
                    _cputws(itr->path().wstring().c_str());
                    _cputws(L"\n");
                    dir.push_back(itr->path());
                    cout << dir.size() << endl;
                }
            }
        }
    }
    
    int main() {
        vector<path> dirs;
    
        iterateDirs(".", dirs);
        for (path p : dirs) {
            _cputws(p.wstring().c_str());
            _cputws(L"\n");
        }
        return 0;
    }
    

    produces next output in cmd with raster fonts:

    C:\w\1>test
    .\CMakeFiles
    1
    .\??????????????
    2
    .\CMakeFiles
    .\??????????????
    

    and next output in cmd in conemu

    C:\w\1>test
    .\CMakeFiles
    1
    .\اختبارテスト試験Про
    2
    .\CMakeFiles
    .\اختبارテスト試験Про
    

    So before running your app, you need to make sure that you could see directory names with dir for example.