2009-05-07 13 views
6

私はICUとutf8のような小さなライブラリを知っています(正確な名前は忘れてください)。しかし、これらのどれも私が望むものではありません。C++ unicodeの質問

私が本当に欲しいのは、ICUのようなものですが、よりフレンドリーな方法で包み込まれています。

具体:

  • 完全
  • C++標準ストリームの実装、又は同じ役割を行う少なくとも何かを配向オブジェクト。
  • 時間、日付などをロケールに依存した形式でフォーマットすることができます(英国ではdd/mm/yy、米国ではmm/dd/yy)。
  • 文字列の「内部」エンコーディングを選択できるようにするため、Windows APIとDirectXとの間で文字列を渡すときにたくさんの変換を避けるために、Windows上でUTF-16を使用することができます。
  • 簡単な文字列変換エンコーディング

の間には、そのようなライブラリが存在しない場合は、標準C++のクラスを使用してICUをラップすることが可能であるので、私は、例えばはstdと同一の用法を持っているのUStringを作成することができます::文字列とstd :: wstringのまた、ストリームのバージョンを実装することもできます(既存のものと完全に互換性があります。つまり、std :: ostreamを期待する関数に渡すことができます。 d ascii(またはutf-8)をオンザフライで実行していますか?それはどれくらいの仕事が可能だろうと仮定しますか?

EDIT: また、utf8、utf16、utf32のC++ 0x標準と注目リテラルを見れば、標準ライブラリ(文字列、ストリームなど)がこれらのエンコードを完全にサポートし、それら? Visual Studioがこれらの機能をサポートするまでどれくらいの時間がかかりますか?

EDIT2: 既存のC++サポートを使用する場合は、ロケールとファセットを参照します。

私が遭遇した問題の1つは、wchar_tの周りに定義されているストリームをファイルi/oのためのウィンドウの下に2バイトで使用すると、それ自身のファイルにはまだasciiを使用しているようです。
FF FE:

はかなりの期待UTF-16出力よりも明らかにASCIIで0Dの0A

48 65 6C 6C 6F 20 57 6F 72 6C 64ファイルに次ヘクスをもたらし48 00 65 00 6C 00 6C 00 6F 00 20 00 57 00 6F 00 72 00 6C 00 64 00 0D 00 0A 00

+0

UTF-16テキストは実際に**ローカルの8ビットエンコードに**変換**されています!だからあなたはutf-16をファイルに書き込まない。 std :: locale :: global(std :: locale());を呼び出すことを忘れないでください。 – Artyom

+0

これでファイルをエンコードする方法を教えてください。私はstd :: localを試しました...あなたは上記のように言いましたが、何の効果もないようです:( –

+0

システムロケール 'ru_RU.UTF-8'なら、エンコーディングはutf-8です。あなたが他のロケールを指定することもできます: 'locale :: globale(locale(" de_DE.ISO-8859-1 "));'(注意、私はPOSIX名のロケール名を使用しています.Windowsあなたはロケール名が – Artyom

答えて

1

特定のロケールを指定することで、日付、時刻などの書式設定を行うことができます。あなた自身のためには、必要に応じて基礎となる図書館から多かれ少なかれ取ることが常に可能です。

また、C++ 0xの標準を見て、UTF8、UTF16およびUTF32のためのリテラルに気づいた、それは標準ライブラリ(例えば文字列は、ストリーム、など)完全にそれらのencodeingsとそれらの間の変換をサポートすることを意味してい?

はい。しかし、これらは異なるデータタイプであり、通常のwcharシーケンスまたはwstringシーケンスではありません。

Visual Studioがこれらの機能をサポートするまでどのくらいの時間がかかるのでしょうか?

私の知る限り、vc9(VS2008)は一部のTR1機能のみを部分的にサポートしています。 vc10(VS2010)はより良いサポートを期待しています。

+0

はい、しかし、それは特定のエンコードにはフォーマットされていませんが、ASCII文字列にフォーマットしてからエンコードすることは可能ですが、アスキーでは不可能なchineaseで長い月の名前を使用したい場合はどうすればいいですか? –

+0

ロケールが演出されます。また、ファセットをルックアップします。 – dirkgently

+0

はい。ナリティー。ユーザーにフォーマットを強制しないでください。システムでフォーマットを決定させるには、ロケールが正しく設定されていることを確認してからストリームが正しく動作するようにします。 (+1) –

3

私が本当にしたいことはICUのようなものですが、残念ながら、より友好的に

を包ん、そのような事はありません。彼らのAPIはそれほどひどいわけではないので、あなたは何らかの努力をしてそれに慣れることができます。

時間、日付などをロケールに応じてフォーマットできます(英国ではdd/mm/yy、米国ではmm/dd/yy)。

std::localeクラスに完全サポートされています。使用方法はこちらをご覧ください。 std::iostreamのロケールを指定することもできます。これにより、数値、日付の書式が正しく設定されます。エンコーディング

std::locale広い一方と背面に8ビットをローカルエンコーディングをcovertingためのファセットを提供するとの間の文字列の変換

簡単。

ので、私は、例えば、それはUTF-16

ICUを使用することができますが、UTF-16は、内部で、他のOSの下でのWin32 wchar_tとwstringの使用UTF-16だけでなく、実装のほとんどのようにwchar_tを与える使用していますutf-32を使用し、wstringはutf-32を使用します。

備考:std::localeのサポートは完全ではありませんが、すでにチャーターの操作に役立つ多くのツールを提供しています。

参照:http://www.cplusplus.com/reference/std/locale/

-1

私は自分の小さなラッパーをしました。あなたが望むなら分かち合うことができます。

+0

これはC++ストリームをサポートしていますか?私の主なICU問題と私は非常に大きなアプリケーションを持っているので、ユニコードで作業したいからです。 –

+0

はい、boost :: iostreamsフィルタを使用します – piotr

-1

タフ運です。私はDinkumwareライブラリがUnicodeをサポートしていることを知っています。あなたはそのWebサイトのドキュメントを見ることができます。 AFAIK、それは無料ではありません。

2

これは私がSTDの間で変換するためにICUを使用する方法である::(UTF-8での)文字列とstd ::それを使用して

/** Converts a std::wstring into a std::string with UTF-8 encoding. 
*/ 
template < typename StringT > 
StringT utf8 (std::wstring const & rc_string); 

/** Converts a std::String with UTF-8 encoding into a std::wstring. 
*/ 
template < typename StringT > 
StringT utf8 (std::string const & rc_string); 

/** Nop specialization for std::string. 
*/ 
template < > 
inline std::string utf8 (std::string const & rc_string) 
{ 
    return rc_string; 
} 

/** Nop specialization for std::wstring. 
*/ 
template < > 
inline std::wstring utf8 (std::wstring const & rc_string) 
{ 
    return rc_string; 
} 

template < > 
std::string utf8 (std::wstring const & rc_string) 
{ 
    std::string result; 
    if(rc_string.empty()) 
    return result; 

    std::vector<UChar> buffer; 

    result.resize(rc_string.size() * 3); // UTF-8 uses max 3 bytes per char 
    buffer.resize(rc_string.size() * 2); // UTF-16 uses max 2 bytes per char 

    UErrorCode status = U_ZERO_ERROR; 
    int32_t len = 0; 

    u_strFromWCS(
    &buffer[0], 
    buffer.size(), 
    &len, 
    &rc_string[0], 
    rc_string.size(), 
    &status 
); 
    if(!U_SUCCESS(status)) 
    { 
    throw XXXException("utf8: u_strFromWCS failed"); 
    } 
    buffer.resize(len); 

    u_strToUTF8(
    &result[0], 
    result.size(), 
    &len, 
    &buffer[0], 
    buffer.size(), 
    &status 
); 
    if(!U_SUCCESS(status)) 
    { 
    throw XXXException("utf8: u_strToUTF8 failed"); 
    } 
    result.resize(len); 

    return result; 
}/* end of utf8 () */ 


template < > 
std::wstring utf8 (std::string const & rc_string) 
{ 
    std::wstring result; 
    if(rc_string.empty()) 
    return result; 

    std::vector<UChar> buffer; 

    result.resize(rc_string.size()); 
    buffer.resize(rc_string.size()); 

    UErrorCode status = U_ZERO_ERROR; 
    int32_t len = 0; 

    u_strFromUTF8(
    &buffer[0], 
    buffer.size(), 
    &len, 
    &rc_string[0], 
    rc_string.size(), 
    &status 
); 
    if(!U_SUCCESS(status)) 
    { 
    throw XXXException("utf8: u_strFromUTF8 failed"); 
    } 
    buffer.resize(len); 

    u_strToWCS(
    &result[0], 
    result.size(), 
    &len, 
    &buffer[0], 
    buffer.size(), 
    &status 
); 
    if(!U_SUCCESS(status)) 
    { 
    throw XXXException("utf8: u_strToWCS failed"); 
    } 
    result.resize(len); 

    return result; 
}/* end of utf8 () */ 

をwstringのはそれと同じくらい簡単です:

std::string s = utf8<std::string>(std::wstring(L"some string")); 
std::wstring s = utf8<std::wstring>(std::string("some string")); 
+0

1つのバグ:UTF-8は1文字あたり最大* 4バイトを使用します。 誤った用語の使用:UTF-16は1文字につき最大2 *コード単位*を使用します。 – dalle

1

私はいつもこのような方法を作業:いくつかのエンコーディングの

バイトストリームを - > - > wistream - > STL &ブースト - > wostream - > は - >いくつかでストリームをバイトエンコード