2017-09-25 1 views
0

私はboost filestreamsで問題に遭遇しました。私はWindowsの下のユーザーディレクトリにファイルを作成して変更する必要があります。しかし、ユーザ名にはウムラウトが含まれているため、MinGWでコンパイルすると失敗します。標準では、boostest useのfilestreamのためのwide_char open()APIがありません。 Read/Write file with unicode file name with plain C++/Boost,とhttps://svn.boost.org/trac10/ticket/9968MinGWの下にboost :: filestreamを持つUTF-8の名前

しかし、この問題は主にシステムコードページ外の文字を使用しようとしたときに発生していました。私の場合は、明らかにユーザーディレクトリが存在するため、システムコードページの文字のみを使用しています。これは私が後押し::パスをUTF8をbeeingてますが(boost::fstream::openに起こる)string()メンバ関数を呼び出すときに、システムのエンコーディングに変換するように、すべてのstd::stringのを期待して言うことができるなら、私はそう、これは動作する必要があること、

を思わせます基本的には:自動的にブースト(およびロケールを強化)を使用してその変換(UTF8 - >システムエンコード)を行う方法はありますか?ここでは完全であることを

は、ロケールを設定するための私のコードです:

#ifdef _WIN32 
     // On windows we want to enforce the encoding (mostly UTF8). Also using "" would use the default which uses "wrong" separators 
     std::locale::global(boost::locale::generator().generate("C")); 
#else 
     // In linux/OSX this suffices 
     std::locale::global(std::locale::classic()); 
#endif // _WIN32 
     // Use also the encoding (mostly UTF8) for bfs paths 
     bfs::path::imbue(std::locale()); 

答えて

1

私は両方が自分の欠点を持っている別のライブラリを使用して2つの解決策を見つけました。

  1. PathieDocu)これは、シンボリックリンクの作成およびその他のファイル/フォルダ操作と同様の取り扱いUTF8意識ストリームとパスを提供するブースト::ファイルシステムの完全な交換のように見えます。
    欠点:静的ビルドにはバグがあるため、動的ライブラリとしてのみ動作します。あなたがすでにブーストを使用している場合は、余計かもしれません。
  2. Boost.NoWideDocu)Windows上でUTF8をサポートするほぼすべてのファイルハンドラおよびストリームハンドラに代わるものを提供し、他のものの標準機能にフォールバックします。 filestreamはUTF8でエンコードされた値(名前のため)を受け取り、それはboost自体を使用します。
    欠点:パスの処理がなく、bfs::pathまたはワイド文字列(Windowsの場合はbfs::path内部形式はUTF16)を受け入れないため、パッチは必要ですが、シンプルです。また、std::coutなどをUTF8文字列で使用する場合は、Windows用のビルドも必要です。
    もう一つのすばらしいこと:Windows上でargc/argvをUTF8に変換するクラスを提供します。
1

WindowsはUTF-16ではなく、UTF-8を使用していますので、それは、Windows上の問題です。私はあなたの非常に問題解決するために、定期的にこの機能を使用します(。私はここに投稿するにはいくつかのことを取り除かれている)

// get_filename_token.cpp 

// Turns a UTF-8 filename into something you can pass to fstream::open() on 
// Windows. Returns the argument on other systems. 

// Copyright 2013 Michael Thomas Greer 
// Distributed under the Boost Software License, Version 1.0. 
// (See accompanying file LICENSE_1_0.txt 
// or copy at   http://www.boost.org/LICENSE_1_0.txt) 

#ifdef _WIN32 

#include <string> 

#ifndef NOMINMAX 
#define NOMINMAX 
#endif 
#include <windows.h> 

std::string get_filename_token(const std::string& filename) 
    { 
    // Convert the UTF-8 argument path to a Windows-friendly UTF-16 path 
    wchar_t* widepath = new wchar_t[ filename.length() + 1 ]; 
    MultiByteToWideChar(CP_UTF8, 0, filename.c_str(), -1, widepath, filename.length() + 1); 

    // Now get the 8.5 version of the name 
    DWORD n = GetShortPathNameW(widepath, NULL, 0); 
    wchar_t* shortpath = new wchar_t[ n ]; 
    GetShortPathNameW(widepath, shortpath, n); 

    // Convert the short version back to a C++-friendly char version 
    n = WideCharToMultiByte(CP_UTF8, 0, shortpath, -1, NULL, 0, NULL, NULL); 
    char* ansipath = new char[ n ]; 
    WideCharToMultiByte(CP_UTF8, 0, shortpath, -1, ansipath, n, NULL, NULL); 

    std::string result(ansipath); 

    delete [] ansipath; 
    delete [] shortpath; 
    delete [] widepath; 

    return result; 
    } 

#else 

std::string get_filename_token(const std::string& filename) 
    { 
    // For all other systems, just return the argument UTF-8 string. 
    return filename; 
    } 

#endif 

+0

ええ、私はそのように下に行く必要があると思った。私は、新しいオープン関数と関数を提供するだけのboostクラスのように機能する新しいiofstreamクラスを作成することを考えていました。あなたはなぜUTF8に戻って変換していますか? 'CP_ACP'はもっと適しているでしょうか?これはかなりシンプルだと思われるので、なぜブーストはそうしないのですか? 8.3の名前のような欠点は、常にANSIかそうではないのですか? – Flamefire

+0

ドローバックが見つかりました:これは既存のファイルでのみ機能します。したがって、ファイルが実際に存在するかどうかを確認する必要があります。これは、ワイド文字で作成を実装しようとしたときに競合状態になる可能性があります。 – Flamefire

+0

クロスプラットフォームなので。すべての現代* nixenはUTF-8ファイル名を開き、古いコードを破壊しません。同様に_all_ Windowsファイル名は、技術的にUTF-8サブセットである、OSで許容される8.3ファイル名「トークン」に変換することができます。 –

関連する問題