2017-02-22 5 views
1

これまでユニコード、そのエンコーディングおよび関連する多くのトピックについて何度も読んできました。
私の研究の背後にある理由は、ファイルの内容を読み込み、文字で解析するためです。私が間違っている場合C++ユニコード文字が1バイトよりも大きいファイルを正しく読み取る

は私にしてください修正:

C++のgetc()戻りEOFに等しいかもしれないintを。
戻り値がEOFと等しくない場合は、 とすると、charに安全に割り当てられます。
std::stringcharを基にしているため、これらの文字でstd::stringを作成して使用することができます。

私はstringにC#のchar(16ビット)を使用するC#バックグラウンドを持っています。
charの値は、ユニコード値に直接マッピングされます。
charの値が5であるユニコード文字は、U+0005に位置します。

私が理解していないのは、値がバイトより大きいかもしれない文字を含むC++のファイルを読む方法です。私はgetc()を使用して、値が1バイトに制限されている文字だけを読むことができるときには快適ではないと感じています。

C++でファイルを正しく読み取る方法について、重要な点がありません。
洞察力は非常に高く評価されています。

私はvC++を使用してWindows 10 x64を実行しています。
しかし、可能であれば、この質問はプラットフォームに依存しないようにしておきたいと思います。
How well is Unicode supported in C++11?

それはユニコードがサポートされているどのように悪いに迅速にダイビングです:(?)私はKlitos Kyriacouのコメントにリンクスタックオーバーフローポストを強調したいと思います

EDIT

C++で。
詳細については、受け入れられた回答に記載されているリソースを参照してください。

+0

'std :: wstring'や' wchar_t'を見たことがありますか? –

+2

どのエンコードを使用しますか? –

+0

@VadaPochéそれを読みましょう... –

答えて

0

Unicode in C++ by James McNellisを見ることをおすすめします。
これは、Unicodeを扱うときにC++に役立つものとそうでないものを説明するのに役立ちます。
C++にはUTF8で簡単に作業するための優れたサポートがないことがわかります。

各グリフ(コードポイントだけではなく)を繰り返し処理するように思えるので、
複雑な処理を行うために3番目のparyライブラリを使用することをおすすめします。
utfcppは私にとってはうまくいきました。

+0

あなたがリンクしている話は、C++のUnicodeサポートにいくつかの重要な洞察を提供します。私はgerneral(C++だけでなく)の文字エンコーディングをよりよく理解したいと思う人にお勧めします。私はutfcppと一緒に行くつもりです。なぜなら、私は、1)検証と2)変換のための最良の機能を提供すると思われるからです。 –

2

Windows APIと互換性のある16ビットの「文字」に相当するのは、wchar_tです。ただし、プラットフォームに依存しない方法でUTF-16でエンコードされた文字列を格納する場合は、char16_tを使用してください。

Windowsプラットフォームでchar16_tを使用する場合は、文字列をOS APIに渡すときにいくつかのキャストを行う必要があります。

同等の文字列型は、次のとおり

  • std::wstring(wchar_t型)
  • std::u16string(char16_t)

ファイルストリームタイプ:

  • std::wifstreamstd::basic_ifstream<wchar_t>のtypedef)
  • std::basic_ifstream<char16_t>
  • std::wofstream
  • UTF-16文字列にUTF-8でエンコードされたファイルを読み取る(std::basic_ofstream<wchar_t>のtypedef)
  • std::basic_ofstream<char16_t>

例:どの

#include <windows.h> 
#include <fstream> 
#include <string> 
#include <locale> 
#include <codecvt> 

int main() 
{ 
    std::wifstream file(L"test_utf8.txt"); 

    // Apply a locale to read UTF-8 file, skip the BOM if present and convert to UTF-16. 
    file.imbue(std::locale(file.getloc(), 
     new std::codecvt_utf8_utf16<wchar_t, 0x10ffff, std::consume_header>)); 

    std::wstring str; 
    std::getline(file, str); 

    ::MessageBox(0, str.data(), L"test", 0); 

    return 0; 
} 

UTF-16でエンコードされたファイルを16ビットのstd::wstringまたはstd::u16stringに読み込む?

明らかにこれは簡単ではありません。 std::codecvt_utf16がありますが、16ビットwchar_t文字タイプで使用すると、UCS-2が生成されますが、これはUTF-16のサブセットであるため、サロゲートペアは正しく読み取られません。 cppreference exampleを参照してください。

実際にはまったく役に立たないので、C++ ISO委員会がどのようにこの決定に至ったのかわかりません。少なくとも自分たちをUCS-2に制限するか、完全なUTF-16範囲を読みたいかを選択できるように、フラグを用意しておく必要があります。

多分別の解決策がありますが、今は私はそれを認識していません。

+0

+1複数の理由:私は今、私はUTF8、異なるファイルストリームを記述し、UTF8とUTF16の両方のサンプルを提供するために使用すべきではないと思うwstringとwchar_tを指摘します。私は答えとしてこれを受け入れませんでした。なぜなら、私が理解できる/書いているサンプルよりも、utfcpp(Trevorに言及されている)のようなライブラリが検証とデコードをはるかに上手く処理できると信じているからです。それでも、誰かが自分で書いた解決策を探しているなら、これはおそらく行く方法です。 info zett42に感謝します:) –

+0

残念ながら、UTF-16の例はUCS-2(上記参照)のみを読み込むため、削除する必要がありました。ドキュメントをもっと慎重に読んでください... – zett42

+0

ファイルをバイナリとして読んでください。簡単に動作する標準ライブラリのマシンを使用してください。何か別の場所で実行してください。過去の私の "何か他のことをする"には、最初からUTF-8コーデックベータを書くことが含まれていましたが、今ではC++ 11以降では、ライブラリはその点で十分ではありません。 –

1

Cのgetc()は1970年代に書かれたという状況です。すべての意図と目的に対して、「文字を読む」ではなく「オクテットを読む」ことを意味します。事実上、すべてのバイナリデータはオクテット上に構築されます。

Unicodeは、オクテットが表すことができる範囲を超える文字を許可します。だから、うっかり、Unicodeの人々は16ビット文字の標準を提案しました。マイクロソフトはこの提案を早期に取り入れ、ワイド文字(wchar_tなど)をWindowsに追加しました。 1つの問題は、16ビットですべての人間の言語のすべてのグリフをステータスで表現するには不十分であり、もう1つはバイナリファイルのエンディアンであるということでした。そこで、Unicodeの人々は32ビットのUnicode標準を追加しなければなりませんでした。そして、Unicodeファイルの始めに少しのエンニャネスとフォーマットタグを組み込んでいました。最後に、16ビットのUnicodeグリフは、Microsoftのwchar_tグリフとは完全に一致しませんでした。

その結果、混乱が生じました。完全な精度と移植性で16または32ビットのUnicodeファイルを読み込んで表示することは非常に困難です。また、非常に多くのプログラムがまだ8ビットASCIIを使用していました。

幸いにも、UTF-8が発明されました。UTF-8は、7ビットのasciiと下位互換性があります。最上位ビットが設定されている場合、グリフは複数の文字でエンコードされ、いくつの文字が表示されるかがわかります。ヌルバイトは、文字列の終わりのインジケータ以外は表示されません。したがって、ほとんどのプログラムは、文字列を分割したり、そうでなければ英語として扱おうとしない限り、UTF-8を正しく処理します。

可変長ルールのため、UTF-8はcharへのランダムアクセスが不可能であるというペナルティがあります。しかしそれは小さな欠点です。一般的にUTF-8は、Unicodeテキストを保存してプログラムに渡す方法です。グリフが実際に必要な場合にのみ、Unicodeコードポイントに分解してください。表示のために。

+0

+1の履歴を提供します。開発者がサロゲートペアを認識していなくても、UCS-2のコードポイントでテストするのが最も好きなので、99%の時間がかかるため、UTF-16は非常にエラーが発生しやすいと言わなければなりません。 – zett42

+0

* UTF-8には、charsへのランダムアクセスが不可能であるというペナルティがあります。* ... UTF-16やUTF-32でも当てはまります。なぜなら、[abstract character](https://en.wikipedia.org/wiki/Unicode#Abstract_characters)は、複数のユニコード文字で構成できます。 – zett42

関連する問題