2009-08-13 12 views
12

ワイファイストリームを使用してワイド文字列(std :: wstring)にテキストファイルを読み込むと、ストリーム実装ではさまざまなエンコーディングがサポートされます。 ASCII、UTF-8、およびUTF-16ファイルifstreamは異なるエンコーディングをサポートします

もしそうでなければ、私は何をしなければなりませんか?

+2

ストリームをロケールで埋め込む方法。 http://stackoverflow.com/questions/207662/writing-utf16-to-file-in-binary-mode/208431#208431 –

答えて

21

C++は、std::localeとファセットstd::codecvtを使用して文字エンコードをサポートしています。一般的な考え方は、localeオブジェクトは、文化によって異なる(人間の)言語から言語に変化する可能性のあるシステムの側面を記述しているということです。これらの側面は、facetに分類されます。これは、ローカライゼーションに依存するオブジェクト(I/Oストリームを含む)の構築方法を定義するテンプレート引数です。 istreamから読み取ったり、ostreamに書き込んだりすると、各文字の実際の書き込みは、ロケールのファセットによってフィルタされます。ファセットは、ユニコードタイプのエンコードだけでなく、どのくらいの数(例えば、カンマまたはピリオド)、通貨、時間、大文字、およびその他の詳細のような様々な特徴をカバーする。

エンコーディングを行う機能が存在するという理由だけで、標準ライブラリが実際にすべてのエンコーディングを処理するわけではなく、そのようなコードを簡単に行うこともできません。 wchar_tが小さすぎる(データをマングリングする)か、大きすぎる(スペースを無駄にする)ことがあり、最も一般的なコンパイラーであることがあるため、 Visual C++やGnu C++など)doは、実装の大きさが異なります。したがって、通常、実際のエンコーディングを行うには外部ライブラリを見つける必要があります。

  • iconvは、一般的に正しいことを認めるが、C++のメカニズムにバインドする方法の例を見つけるのは難しいです。非常に徹底しているが、C++ APIが標準とうまく再生しようとしません
  • jla3ep mentionslibICU、(私の知る限り:あなたはより良い行うことができますかどうかを確認するためにexamplesをスキャンすることができます)

BoostのUTF-8 codecvt facetから、すべての基本をカバーする最も簡単な例があります。具体的には、IOストリームで使用するためにUTF-8(UCS4)をエンコードしようとしている例です。私はちょうどそれをそのままコピーすることを勧めませんが、このように見えます。それはそれを理解するためにthe sourceに掘りもう少しかかる(と私は主張しません):

typedef wchar_t ucs4_t; 

std::locale old_locale; 
std::locale utf8_locale(old_locale,new utf8_codecvt_facet<ucs4_t>); 

... 

std::wifstream input_file("data.utf8"); 
input_file.imbue(utf8_locale); 
ucs4_t item = 0; 
while (ifs >> item) { ... } 

ロケールについての詳細を理解するために、どのように彼らは(codecvt含む)ファセットを使用して、次を見てみましょう:

+1

素敵な要約。 http://www.amazon.com/dp/0201183951を書籍リストに追加することもできます。それは私が知っている問題の最も徹底的な扱いです。 – sbi

+0

sbi:本をリストに追加しました。素晴らしいリンクをありがとう。 – quark

1

ワイド文字列とワイド文字列の前の日付のUTF-8、UTF-16とUnicodeの設計を(私はそれが違いを作る場合は、ファイル全体を読み込む必要があります)。テクニカルになりたい場合は、標準文字列と標準ストリームが必ずしもASCIIで動作するとは限りません(基本的にそこにあるすべてのコンピュータはASCIIを使用しているため、潜在的にEBCDICマシンがあります)。

Raymond Chen once wrote a series illustrating how to work with different wide character stream/string types

4

ifstreamは、ファイルのエンコードを気にしません。ファイルから文字(バイト)を読み込むだけです。 wifstreamはワイドバイト(wchar_t)を読み込みますが、ファイルのエンコードについてはまだ分かりません。 wifstreamは、Unicodeの固定長文字エンコーディング(各文字は2バイトで表されます)のUCS-2には十分です。

IBM ICUライブラリを使用して、Unicodeファイルを処理できます。アプリケーションはすべてのプラットフォームで同じ結果を与える

国際Unicodeのコンポーネント(ICU)UnicodeサポートのためのC/C++やJavaのライブラリの成熟した、ポータブル・セットで、ソフトウェアの国際化(I18N)とグローバル化(G11N)を、 。

ICUは、市販のソフトウェアと他のオープンソースまたはフリーソフトウェアの両方で使用するのに適した非限定的なオープンソースライセンスの下で公開されています。

+1

「ifstream」がエンコーディングを抄録していると言うのは、もう少し正しいと思います。ロケール(標準C++の場合)、およびOSまたはライブラリ固有のi18n機能を使用して、下位レベルの機能を使用します。 ifstreamは気にしないかもしれませんが、あなたはこのケースで何を呼び出すか気にします。 – quark

+3

'locales'はUnicodeのエンコーディングとは関係ありません。ロケールを設定しているときは、コンソール上のシンボルをどのように表現するべきかのヒントを 'iostream'に与えるだけです。しかし、* file *のエンコーディングは検出できません。また、ifstreamを使用してANSIとUTF-8を区別することは不可能です。 –

関連する問題