web-dev-qa-db-ja.com

UTF-16は有害であると考えるべきですか?

おそらくかなり物議を醸している質問は何でしょうか。「最も人気のあるエンコーディングの1つであるUTF-16は有害であると考えられるべきでしょうか?」

なぜ私はこの質問をするのですか?

UTF-16が実際には可変長エンコーディングであることを知っているプログラマは何人いますか?これは、サロゲートペアとして表され、複数の要素をとるコードポイントがあることを意味します。

知っている; Javaの文字列、C#の文字列、Win32 API、Qt GUIライブラリ、ICU Unicodeライブラリなど)など、多くのアプリケーション、フレームワーク、およびAPIがUTF-16を使用します。 BMP(2つのUTF-16要素を使用してエンコードする必要がある文字))からの文字の処理には、多くの基本的なバグがあります。

たとえば、次のいずれかの文字を編集してみます。

  • ????( + 1D11EMUSICAL SYMBOL G CLEF
  • ????( + 1D565数学的なダブルストロークの小T
  • ????( + 1D7F6数学的モノスペースデジットゼロ
  • ????( + 2008Aハン文字

インストールしたフォントによっては、一部が表示されない場合があります。これらの文字はすべてBMP(Basic Multilingual Plane)の外にあります。これらの文字が表示されない場合は、 nicode文字参照 でそれらを確認してみてください。

たとえば、これらの文字を含むファイル名をWindowsで作成してみてください。これらの文字を「バックスペース」で削除して、UTF-16を使用するさまざまなアプリケーションでの動作を確認してください。私はいくつかのテストを行いましたが、結果はかなり悪いです:

  • Operaはそれらの編集に問題があります(バックスペースでの必要な2プレスの削除)
  • メモ帳はそれらを正しく処理できません(バックスペースで必要な2回のプレスを削除してください)
  • ウィンドウダイアログでのファイル名の編集が壊れている(削除に必要な2回のバックスペースプレス)
  • すべてのQT3アプリケーションはそれらを扱うことができません-1つのシンボルの代わりにtwo空の四角を表示します。
  • 一部のプラットフォームでは、XがBMP外の文字である場合、Pythonはそのような文字を直接使用すると誤ってエンコードしますu'X'!=unicode('X','utf-16')
  • pythonがUTF-16 Unicode文字列でコンパイルされている場合、Python 2.5 unicodedataはそのような文字のプロパティを取得できません。
  • StackOverflowは、Unicode文字として直接編集すると、これらの文字をテキストから削除するようです(これらの文字はHTML Unicodeエスケープを使用して表示されます)。
  • WinForms TextBoxは無効な文字列を生成する可能性があります MaxLengthで制限されている場合。

このようなバグは、UTF-16を使用する多くのアプリケーションで非常に見つけやすいようです。

それで... UTF-16は有害だと考えるべきだと思いますか?

432
Artyom

これは古い答えです。
最新のアップデートについては TF-8 Everywhere を参照してください。

意見:はい、UTF-16は有害であると考えるべきです。それが存在するまさにその理由は、ワイドチャーがUCS-4が今あるものになるであろうという誤った信念が以前にあったためでした。

UTF-8の「anglo-centrism」にもかかわらず、それはテキストのための唯一の有用なエンコーディングと考えられるべきです。プログラムのソースコード、WebページとXMLファイル、OSファイル名、およびその他のコンピューター間のテキストインターフェイスが存在してはならなかったと主張することができます。しかし、彼らがそうするとき、テキストは人間の読者のためだけではありません。

一方、UTF-8のオーバーヘッドはわずかな代償ですが、大きな利点があります。 _char*_で文字列を渡すだけの認識されないコードとの互換性などの利点。これは素晴らしいことです。 UTF-8よりもUTF-16で短い文字はほとんどありません。

他のすべてのエンコーディングは最終的にはなくなると思います。これには、MS-Windows、Java、ICU、pythonそれをお気に入りとして使用するのをやめることを含みます。長い調査と議論の後、 my company での開発規則はUTFの使用を禁止します-16 OS API呼び出しを除くすべての場所。これは、アプリケーションでのパフォーマンスの重要性とWindowsを使用しているという事実にもかかわらず、常に想定されるUTF8 _std::string_ sをネイティブのUTF-16に変換するために開発されました。 正しくサポートされていません

必要な場所で必要なものを使用する」と言う人にとって、私は言います:どこでも同じエンコーディングを使用することには大きな利点があり、そうでない場合には十分な理由がありません。特に、C++に_wchar_t_を追加するのは誤りであったと思います。C++ 0xにUnicodeを追加する場合も同様です。ただし、STL実装から要求される必要があるのは、すべての_std::string_または_char*_パラメーターがユニコード互換と見なされることです。

また、「好きなものを使う」というアプローチにも反対しています。私にはそのような自由の理由はありません。テキストの主題については十分な混乱があり、このすべてのソフトウェアが壊れています。上記のことを言っても、プログラマーは最終的に適切な方法の1つとしてUTF-8でコンセンサスに達しなければならないことを確信しています。 (私は非ASCII言語の国から来て、Windowsで育ったので、宗教的根拠に基づいてUTF-16を攻撃することが最後に予想されます)。

Windowsでテキストを作成する方法、およびコンパイル時にチェックされるユニコードの正確性、使いやすさ、およびコードのマルチプラットフォーム性を向上させるために他の人にすすめることについて、もっと情報を共有したいと思います。この提案は、ウィンドウズでUnicodeを使用する適切な方法として通常推奨されるものとは大きく異なります。しかし、これらの推奨事項を詳細に調査した結果、同じ結論が得られました。だからここに行く:

  • UTF-16を受け入れるAPIの隣接ポイント以外の場所で_wchar_t_または_std::wstring_を使用しないでください。
  • _T("")または_L""_ UTF-16リテラルを使用しないでください(UTF-16の廃止の一環として、IMOを標準から除外する必要があります)。
  • LPTSTRCreateWindow()などの__UNICODE_定数に依存する型、関数、またはそれらの派生物は使用しないでください。
  • ただし、__UNICODE_文字列がWinAPIにサイレントコンパイルされないようにするために、常に_char*_が定義されています。
  • プログラム内の_std::strings_および_char*_は、UTF-8と見なされます(特に明記されていない場合)
  • すべての文字列は_std::string_ですが、char *または文字列リテラルをconvert(const std::string &)に渡すことができます。
  • ワイド文字(LPWSTR)を受け入れるWin32関数のみを使用します。 LPTSTRまたはLPSTRを受け入れるものは決して使用しないでください。この方法でパラメータを渡します。

    _::SetWindowTextW(Utils::convert(someStdString or "string litteral").c_str())
    _

    (ポリシーでは、以下の変換関数を使用します。)

  • MFC文字列の場合:

    _CString someoneElse; // something that arrived from MFC. Converted as soon as possible, before passing any further away from the API call:
    
    std::string s = str(boost::format("Hello %s\n") % Convert(someoneElse));
    AfxMessageBox(MfcUtils::Convert(s), _T("Error"), MB_OK);
    _
  • Windowsでのファイル、ファイル名、fstreamの操作:

    • _std::string_または_const char*_ファイル名引数をfstreamファミリに渡さないでください。 MSVC STLはUTF-8引数をサポートしていませんが、次のように使用する必要がある非標準の拡張子があります。
    • _std::string_引数を_std::wstring_を使用して_Utils::Convert_に変換します。

      _std::ifstream ifs(Utils::Convert("hello"),
                        std::ios_base::in |
                        std::ios_base::binary);
      _

      MSVCのfstreamに対する態度が変わった場合は、手動で変換を削除する必要があります。

    • このコードはマルチプラットフォームではなく、将来手動で変更する必要があるかもしれません
    • 詳細については、fstream unicode research/discussion case 4215を参照してください。
    • 非UTF8コンテンツのテキスト出力ファイルを作成しない
    • RAII/OODの理由でfopen()を使用しないでください。必要に応じて、上記の_wfopen()およびWinAPI規則を使用します。

_// For interface to win32 API functions
std::string convert(const std::wstring& str, unsigned int codePage /*= CP_UTF8*/)
{
    // Ask me for implementation..
    ...
}

std::wstring convert(const std::string& str, unsigned int codePage /*= CP_UTF8*/)
{
    // Ask me for implementation..
    ...
}

// Interface to MFC
std::string convert(const CString &mfcString)
{
#ifdef UNICODE
    return Utils::convert(std::wstring(mfcString.GetString()));
#else
    return mfcString.GetString();   // This branch is deprecated.
#endif
}

CString convert(const std::string &s)
{
#ifdef UNICODE
    return CString(Utils::convert(s).c_str());
#else
    Exceptions::Assert(false, "Unicode policy violation. See W569"); // This branch is deprecated as it does not support unicode
    return s.c_str();   
#endif
}
_
340

nicodeコードポイントは文字ではありません!グリフ(ビジュアルフォーム)でさえない場合があります。

いくつかの例:

  • 「ⅲ」のようなローマ数字のコードポイント。 (「iii」のように見える単一の文字。)
  • 「á」のようなアクセント付き文字。単一の結合文字「\ u00e1」または区切り記号「\ u0061\u0301」として表すことができます。
  • ギリシャ語の小文字シグマのような文字で、単語の位置の中間( "σ")と末尾( "ς")の形式は異なりますが、検索の同義語と見なされます。
  • Unicode随意ハイフンU + 00AD。コンテキストに応じて視覚的に表示される場合とされない場合があり、セマンティック検索では無視されます。

Unicode編集を正しく行う唯一の方法は、エキスパートが作成したライブラリを使用するか、エキスパートになって自分で作成することです。コードポイントを数えるだけの場合は、罪の状態に住んでいます。

157
Daniel Newby

使用するUnicode Transformation Form(UTF)についての簡単な経験則があります。-ストレージと通信用のutf-8-データ処理用のutf-16-使用するプラットフォームAPIのほとんどがutf-32の場合utf-32(UNIXの世界では一般的)。

今日のほとんどのシステムはutf-16(Windows、Mac OS、Java、.NET、ICU、Qt)を使用しています。このドキュメントも参照してください: http://unicode.org/notes/tn12/

「有害なUTF-16」に話を戻しますが、間違いなくそうです。

サロゲート(Unicodeを可変長エンコーディングに変換することを考える)を恐れている人は、文字とUnicodeコードポイント間のマッピングを非常に複雑にする他の(非常に大きい)複雑さを理解していません:文字、合字、バリエーションセレクターの組み合わせ、制御文字など.

このシリーズ http://www.siao2.com/2009/06/29/9800913.aspx を読んで、UTF-16がいかに簡単な問題になるかを確認してください。

54
Mihai Nita

そのとおり。

どうして? 運動コードに関係しています。

これらの 大規模コーパスのコードポイント使用統計 を見ると、Tom Christiansenによると、trans-8bit BMPコードポイントは、 -BMPコードポイント:

 2663710 U+002013 ‹–›  GC=Pd    EN DASH
 1065594 U+0000A0 ‹ ›  GC=Zs    NO-BREAK SPACE
 1009762 U+0000B1 ‹±›  GC=Sm    PLUS-MINUS SIGN
  784139 U+002212 ‹−›  GC=Sm    MINUS SIGN
  602377 U+002003 ‹ ›  GC=Zs    EM SPACE

 544 U+01D49E ‹????›  GC=Lu    MATHEMATICAL SCRIPT CAPITAL C
 450 U+01D4AF ‹????›  GC=Lu    MATHEMATICAL SCRIPT CAPITAL T
 385 U+01D4AE ‹????›  GC=Lu    MATHEMATICAL SCRIPT CAPITAL S
 292 U+01D49F ‹????›  GC=Lu    MATHEMATICAL SCRIPT CAPITAL D
 285 U+01D4B3 ‹????›  GC=Lu    MATHEMATICAL SCRIPT CAPITAL X

「テストされていないコードは壊れたコードです」というTDDの言い方をして、「未実行のコードは壊れたコードです」と言い換え、プログラマーが非BMPコードポイントを処理する必要がある頻度を考えてください。

可変幅エンコーディングとしてUTF-16を処理しないことに関連するバグは、UTF-8の同等のバグよりも気付かれない可能性が高くなります。一部のプログラミング言語は、UCS-2の代わりにUTF-16を提供することを保証していません。また、一部のいわゆる高水準プログラミング言語は、コードポイントの代わりにコードユニットへのアクセスを提供しています(Cでさえ、 wchar_tを使用する場合は、一部のプラットフォームで何ができるかに関係なく、コードポイント。

43
ninjalj

UTF-16が有害であると考えられることを考えると、 nicodeの理解を深める を取得する必要があると言います。

私は主観的な質問について自分の意見を提示することに反対票を投じてきたので、詳しく説明しましょう。 UTF-16に悩まされているのは正確には何ですか?すべてがUTF-8でエンコードされていればよろしいですか? UTF-7?または、UCS-4はどうですか?もちろん、特定のアプリケーションはそこにあるすべての文字コードを処理するようには設計されていませんが、特に今日のグローバル情報ドメインでは、国際的な境界間の通信に必要です。

しかし、実際には、UTF-16は混乱している、または不適切に実装されている可能性があるため(Unicodeは確かに可能である)、有害であると見なす必要があると感じた場合、どの文字エンコーディング方式が無害であると見なされますか?

編集:明確にするために:なぜ標準の不適切な実装を、標準自体の品質の反映と見なすのですか?他の人が後で指摘したように、アプリケーションがツールを不適切に使用したからといって、ツール自体に欠陥があるという意味ではありません。その場合、「varキーワードは有害と見なされる」または「スレッドは有害と見なされる」などと言えるでしょう。質問は、標準の品質と性質を、多くのプログラマーが標準を適切に実装および使用する上での困難と混同していると思います。これは、Unicode自体ではなく、Unicodeの仕組みを理解していないことに起因していると思います。

40
patjbs

Utf-16エンコーディングに問題はありません。ただし、16ビット単位を文字として扱う言語は、設計が不適切であると考えられます。常に文字を表すわけではない「char」という名前の型を持つことは、かなり混乱します。ほとんどの開発者は、char型がコードポイントまたは文字を表すことを期待しているため、BMPを越えた文字にさらされると、多くのコードがおそらく壊れます。

ただし、utf-32を使用しても、各32ビットコードポイントが常に文字を表すとは限らないことに注意してください。文字の組み合わせにより、実際の文字は複数のコードポイントで構成される場合があります。 Unicodeは決して簡単なものではありません。

ところで。 Utf-8で供給される、文字が8ビットであることが期待されるプラットフォームおよびアプリケーションには、おそらく同じクラスのバグがあります。

37
JacquesB

私の個人的な選択は、常にUTF-8を使用することです。 Linuxのほぼすべての標準です。多くのレガシーアプリとの下位互換性があります。ラテン文字以外の文字と他のUTF形式に使用される余分なスペースのオーバーヘッドは最小限であり、ラテン文字のスペースが大幅に節約されます。ウェブ上では、ラテン語が最高の支配権を握っており、当面はそうなると思います。そして、元の投稿の主な論点の1つに対処するために:ほとんどすべてのプログラマーは、UTF-8にマルチバイト文字が含まれることを知っています。誰もがこれを正しく処理するわけではありませんが、彼らは通常気づいています。ただし、もちろん、アプリケーションに最も適したものを選択する必要があります。そもそも、複数あるのはそのためです。

20
rmeador

まあ、固定サイズのシンボルを使用するエンコーディングがあります。私は確かにUTF-32を意味します。しかし、各シンボルの4バイトはtoo無駄なスペースの大部分です。なぜ日常の状況でそれを使用するのでしょうか?

私の考えでは、ほとんどの問題は、一部のソフトウェアがUnicode標準に遅れているという事実から生じますが、状況をすぐに修正することはできませんでした。 Opera、Windows、Python、Qt-これらはすべて、UTF-16が広く知られるようになる前、または登場する前に登場しました。しかし、Opera、Windowsエクスプローラー、メモ帳では、BMP以外の文字は問題ありません(少なくとも私のPCでは)。ただし、プログラムが認識しない場合、サロゲートペアの場合、UTF-16は使用されません。このようなプログラムの処理で問題が発生しても、UTF-16自体とは何の関係もありません。

ただし、BMPサポートのみのレガシーソフトウェアの問題は多少誇張されていると思います。BMP=外の文字は、非常に特殊なケースと領域でのみ発生します。 nicodeの公式FAQ に、「東アジアのテキストでも、サロゲートペアの発生率は、平均ですべてのテキストストレージの1%未満である必要があります。」もちろん、BMPプログラムはUnicodeに準拠していないため無視しないでくださいが、ほとんどのプログラムはそのような文字を含むテキストを処理することを目的としていません。それをサポートしないでください、それは不快ですが、破局ではありません。

次に、代替案を検討しましょう。 UTF-16が存在しない場合は、ASCII以外のテキストに適したエンコードがなく、UCS-2用に作成されたすべてのソフトウェアを完全に再設計して、Unicode準拠を維持する必要があります。後者は、おそらくUnicodeの採用を遅らせるだけです。また、ASCIIに関連してUTF-8が行うように、UCS-2のテキストとの互換性を維持できなかったでしょう。

さて、すべてのレガシー問題を脇に置いて、エンコーディング自体に対する議論は何ですか?最近の開発者は、UTF-16が可変長であることを知らないのではないかと疑っています。これは、Wikipediaを使用していたるところに記述されています。複雑さを問題の可能性として指摘した場合、UTF-16はUTF-8よりも解析がはるかに難しくありません。また、UTF-16でのみ文字列の長さを決定するのは簡単ではないと考えるのも誤りです。 UTF-8またはUTF-32を使用する場合でも、1つのUnicodeコードポイントが必ずしも1つの文字を意味するとは限らないことに注意してください。それ以外は、エンコードに関しては特に問題はないと思います。

したがって、エンコーディング自体は有害であると考えるべきではないと思います。 UTF-16はシンプルさとコンパクトさの妥協点であり、必要な場所で必要なものを使用することで害はありません。 ASCIIとの互換性を維持する必要があり、UTF-8が必要な場合もあります。Han表意文字を使用して作業し、UTF-16を使用してスペースを節約したい場合もあります。固定長エンコーディングを使用する文字の普遍的な表現が必要です。より適切なものを使用し、適切に実行してください。

18
Malcolm

特に東アジア言語での長年のWindows国際化作業は私を傷つけた可能性がありますが、私はプログラムの内部から文字列の表現にはUTF-16、プレーンテキストのようなドキュメントのネットワークまたはファイルストレージにはUTF-8に頼っています。ただし、UTF-16は通常Windowsでより高速に処理できるため、WindowsでUTF-16を使用する主な利点です。

UTF-16への移行により、国際的なテキストを扱う平均的な製品の妥当性が劇的に向上しました。サロゲートペアを検討する必要があるのは少数の狭いケース(削除、挿入、および改行)であり、平均的なケースはほとんどが単純なパススルーです。また、JISバリアントのような以前のエンコーディングとは異なり、UTF-16ではサロゲートペアが非常に狭い範囲に制限されるため、チェックは非常に高速で、前後に機能します。

確かに、正しくエンコードされたUTF-8でもほぼ同じくらい高速です。しかし、サロゲートペアを2つのUTF-8シーケンスとして誤ってエンコードする、壊れたUTF-8アプリケーションもたくさんあります。したがって、UTF-8は救済も保証しません。

IEは、通常、UTF-8ページから内部UTF-16表現に変換しているにも関わらず、2000年頃から適切にサロゲートペアを処理します。 Firefoxでも正しく機能していると確信しているので、Operaが何をするかはあまり気にしません。

UTF-32(別名UCS4)は非常にスペースを必要とするため、ほとんどのアプリケーションにとって無意味であり、ほとんどスターターではありません。

16
JasonTrue

UTF-8は間違いなく進むべき道であり、高性能のランダムアクセスを必要とするアルゴリズムで内部的に使用されるUTF-32を伴う可能性があります(ただし、文字の結合は無視されます)。

UTF-16とUTF-32の両方(およびそれらのLE/BEバリアント)には、エンディアンの問題があるため、外部で使用しないでください。

16
Tronic

UTF-16?間違いなく有害です。ここでは私の塩味だけですが、プログラム内のテキストに使用できるエンコードは3つあります。

  • ASCII:これ以上の余裕がない低レベルのもの(例:マイクロコントローラー)を扱う場合
  • UTF8:ファイルなどの固定幅メディアへの保存
  • 整数コードポイント( "CP"?):プログラミング言語とプラットフォームに便利な最大の整数の配列(ASCIIは低リソースの制限で減衰)。古い場合はint32である必要があります。コンピューターおよび64ビットアドレス指定のすべてのint64。

  • 明らかに、レガシーコードへのインターフェイスは、古いコードを正しく機能させるために必要なエンコーディングを使用します。

15
David X

nicodeは、0x10FFFF(1,114,112コード)までのコードポイントを定義します。文字列/ファイル名などを扱う多言語環境で実行されるすべてのアプリケーションは、それを正しく処理する必要があります。

TF-16:1,112,064コードのみをカバーします。 nicodeの最後にあるものは、プレーン15-16(私用領域)からのものです。 tf-16の概念を破ることを除いて、それは将来さらに成長することはできません。

tf-8:理論的には2,216,757,376コードをカバーします。現在のnicodeコードの範囲は、最大4バイトのシーケンスで表すことができます。 バイト順の問題は発生しません。ASCIIと「互換性があります」。

tf-32:理論的には2 ^ 32 = 4,294,967,296コードをカバーします。現在、これは可変長エンコードされておらず、おそらく将来はないでしょう。

これらの事実は自明です。 tf-16の一般的な使用を推奨することは理解できません。それは可変長エンコードされており(インデックスからアクセスできません)、現在でもnicodeの範囲全体をカバーするのに問題があります。バイトオーダーを処理する必要があります。それ以外の利点はありません。 Windowsやその他の場所でネイティブに使用されています。マルチプラットフォームコードを作成するときは、おそらくtf-8をネイティブに使用して、プラットフォームに依存する方法でエンドポイントでのみ変換を行う方がよいでしょう(既に示唆したとおり)。インデックスによる直接アクセスが必要で、メモリに問題がない場合は、tf-32を使用する必要があります。

主な問題は、Windows Unicode = tf-16を扱う多くのプログラマーが、可変長エンコードされていることを知らないか、無視していることです。

* nixプラットフォームでの通常の方法はかなり良いです、c文字列(char *)はtf-8エンコードとして解釈され、ワイドc文字列(wchar_t *)は-として解釈されますtf-32

13
Pavel Machyniak

これをリストに追加します。

提示されたシナリオは単純です(ここで紹介するので、最初よりもさらに単純です!):1. WinForms TextBoxが空のフォームに配置されます。 MaxLengthが20に設定されています。

2.ユーザーがTextBoxに入力するか、テキストを貼り付けます。

3.TextBoxに何を入力または貼り付けても、20に制限されますが、20を超えるテキストではビープ音が鳴ります(ここではYMMV、サウンドスキームを変更してその効果を実現しました!)。

4.テキストの小さなパケットが別の場所に送信され、エキサイティングな冒険が始まります。

これは簡単なシナリオであり、誰もが暇なときにこれを書くことができます。私は、WinFormsを使用して複数のプログラミング言語で自分で書いただけです。そして、複数の実際の言語のテキストを使用しているのは、そのように配線されており、恐ろしい世界全体の誰よりも多くのキーボードレイアウトがあるためです。

私はMagic Carpet Rideというフォームに名前を付けさえして、退屈さを改善しました。

これは価値があるため、機能しませんでした。

代わりに、次の20文字をMagic Carpet Rideに入力しました形:

0123401234012340123 ????

ええとああ。

その最後の文字は、Unicodeの最初の拡張B表意文字であるU + 20000です(別名U + d840 U + dc00、彼の親友には、前のように脱衣されることを恥じていません)...

enter image description here

そして今、私たちはボールゲームを持っています。

TextBox.MaxLength が話しているとき

テキストボックスに手動で入力できる最大文字数を取得または設定します。

それが本当に意味することは

テキストボックスに手動で入力できるUTF-16 LEコードユニットの最大数を取得または設定し、その文字列から生きたがらくたを無慈悲に切り捨てますカプランの仲間と同じくらい執着している人だけが不快感を覚えるだろうという言語の文字概念でキュートなゲームをプレイしようとします(もっと出ていく必要がありますね!)

ドキュメントを更新してみます。
私の CS-2からUTF-16 シリーズを覚えている定期的な読者は、 TextBox.MaxLength の単純な概念による私の不幸と、最小限のケースで、その厳格な動作により不正なシーケンスが作成されます。これは、.Net Frameworkの他の部分がスローする可能性があります。

  • System.Text.EncoderFallbackException:インデックス0のUnicode文字\ uD850を指定されたコードページに変換できません。*

この文字列を.Net Frameworkの他の場所に渡した場合は例外です(同僚のDan Thompsonが行っていたように)。

さて、おそらく完全な CS-2からUTF-16シリーズへ は、多くの人の手の届かないところにあります。
しかし、TextBox.Textが System.String を生成せず、.Net Frameworkの別の部分がスローされないことを期待するのは合理的ではありませんか?つまり、コントロールのイベントの形で、よりスマートな検証を簡単に追加できる次の切り捨てを通知する可能性があるというわけではありません-コントロール自体が行うことを気にしない検証です。私は、このパンクコントロールが安全契約を破っており、予期しない例外を引き起こしてアプリケーションを大まかな種類のサービス拒否としてクラス化できる場合、セキュリティ問題にさえつながる可能性があると言っています。 WinFormsのプロセス、メソッド、アルゴリズム、またはテクニックが無効な結果を生成するのはなぜですか?

出典: Michael S. Kaplan MSDN Blog

11
Yuhong Bao

UTF-16が有害であるとは必ずしも言えません。エレガントではありませんが、GB18030がGB2312で、UTF-8がASCIIで行うように、UCS-2との下位互換性という目的を果たします。

しかし、MicrosoftとSunが16ビット文字を中心に巨大なAPIを構築した後、途中でUnicodeの構造に根本的な変更を加えることは有害でした。変更の認識を広めることに失敗したのはmore有害でした。

9
dan04

まだコメントできないので、utf8everywhere.orgの作者に連絡できないので、これを回答として投稿します。他のstackexchangeで十分な評判があるので、コメント権限を自動的に取得しないのは残念です。

これはへのコメントを意味します。意見:はい、UTF-16は有害であると考えるべきです答え。

1つの小さな修正:

誤ってUTF-8 char*をWindows-API関数のANSI文字列バージョンに渡さないようにするには、_UNICODEではなくUNICODEを定義する必要があります。 _UNICODEは、wcslenではなくMessageBoxではなく、_tcslenなどの関数をMessageBoxWにマップします。代わりに、UNICODE定義が後者を処理します。証明のために、これはMS Visual Studio 2005のWinUser.hヘッダーからのものです。

#ifdef UNICODE
#define MessageBox  MessageBoxW
#else
#define MessageBox  MessageBoxA
#endif // !UNICODE

少なくとも、このエラーはutf8everywhere.orgで修正する必要があります。

提案:

おそらく、このガイドには、データ構造のワイド文字列バージョンの明示的な使用例が含まれているため、見落とす/忘れにくいようにする必要があります。関数のワイド文字列バージョンを使用することに加えて、データ構造のワイド文字列バージョンを使用すると、そのような関数のANSI文字列バージョンを誤って呼び出す可能性がさらに低くなります。

例の例:

WIN32_FIND_DATAW data; // Note the W at the end.
HANDLE hSearch = FindFirstFileW(widen("*.txt").c_str(), &data);
if (hSearch != INVALID_HANDLE_VALUE)
{
    FindClose(hSearch);
    MessageBoxW(nullptr, data.cFileName, nullptr, MB_OK);
}
6
Jelle Geerts

UTF-16は 処理とスペースの間の最良の妥協 であり、それがほとんどの主要なプラットフォーム(Win32、Java、.NET)が文字列の内部表現に使用する理由です。

6

UTF-16のポイントを理解したことがありません。最もスペース効率の良い表現が必要な場合は、UTF-8を使用してください。テキストを固定長として扱えるようにするには、UTF-32を使用します。どちらも必要ない場合は、UTF-16を使用してください。さらに悪いことに、UTF-16の一般的な(基本的な多言語プレーン)文字はすべて単一のコードポイントに収まるため、UTF-16が固定長であると想定するバグは微妙で見つけにくくなります。これをUTF-8で使用すると、国際化しようとするとすぐに、コードが速く大音量で失敗します。

6
dsimcha

UCS4とUTF-32は同じだと誰かが言った。そうではありませんが、私はあなたの意味を知っています。ただし、1つはもう1つのエンコーディングです。ここでもエンディアンの戦いが起こらないように、最初からエンディアンを指定することを彼らが考えていたらいいのにと思います。彼らはそれが来るのを見たことはありませんか?少なくともUTF-8はどこでも同じです(6バイトの元の仕様に従っていない限り)。

UTF-16を使用する場合、マルチバイト文字の処理を含めるにはhaveを使用します。 2Nをバイト配列にインデックス付けしてN番目の文字に移動することはできません。あなたはそれを歩くか、キャラクターインデックスを持っている必要があります。そうでなければ、あなたはバグを書きました。

C++の現在のドラフト仕様では、UTF-32およびUTF-16はリトルエンディアン、ビッグエンディアン、および未指定のバリアントを持つことができると述べています。本当に?ユニコードが最初から全員がリトルエンディアンを実行する必要があると指定した場合、それはすべてより簡単でした。 (私はビッグエンディアンでも大丈夫だったでしょう。)代わりに、何人かはそれを一方的に実装し、もう一方は他の方法で実装しました。ソフトウェアエンジニアであることは恥ずかしいことがあります。

5
Patrick Horgan

開発者が十分に注意を払っていても、害はないと思います。
そして、彼らもよく知っていれば、このトレードオフを受け入れる必要があります。

日本のソフトウェア開発者として、私はUCS-2が十分に大きく、スペースを制限すると明らかにロジックが単純化され、ランタイムメモリが減少するので、UCS-2制限の下でutf-16を使用することで十分です。

コードポイントとバイト数が比例していることを前提とするファイルシステムや他のアプリケーションがあるため、生のコードポイント番号が一定のサイズのストレージに適合することが保証されます。

1つの例は、ファイル名ストレージエンコーディングとしてNTFSおよびVFATがUCS-2を指定です。

それらの例が本当にUCS-4をサポートするように拡張したい場合は、とにかくすべてにutf-8を使用することに同意できますが、固定長には次のような優れた点があります。

  1. 長さによってサイズを保証できます(データサイズとコードポイントの長さは比例します)
  2. ハッシュルックアップにエンコーディング番号を使用できます
  3. 非圧縮データは適切なサイズです(utf-32/UCS-4と比較)

埋め込みデバイスでもメモリ/処理能力が安い将来、追加のキャッシュミスまたはページフォールトと追加のメモリ使用のためにデバイスが少し遅いことを受け入れる可能性がありますが、これは近い将来には発生しないと思います...

2
holmes

「最も一般的なエンコーディングの1つであるUTF-16は有害と見なされますか?」

かなり可能性がありますが、代替案は必ずしもはるかに優れていると見なすべきではありません。

基本的な問題は、グリフ、文字、コードポイント、バイトシーケンスなど、さまざまな概念があることです。これらのそれぞれの間のマッピングは、正規化ライブラリを使用しても、重要です。 (たとえば、ラテン語ベースのスクリプトで記述されたヨーロッパ言語の一部の文字は、単一のUnicodeコードポイントで記述されていません。そして、それは複雑さの最も単純な終わりです!)これは、すべてを正しくすることは驚くほど驚くことです難しい;奇妙なバグが予想されます(そして、ここでそれらについてうめくだけでなく、メンテナに伝えます関係するソフトウェアの=)。

たとえばUTF-8とは対照的に、UTF-16が有害であると見なすことができる唯一の方法は、BMP(ペアとしてコードがコードポイントごとにアクセスまたは反復することを望む場合、それは違いを認識する必要があることを意味します。OTOHは、「文字」を想定する既存のコードの実質的な本体が常に2バイトの量(かなり一般的ですが、間違っていると仮定)は、少なくともすべてを再構築せずに機能し続けることができます。つまり、少なくともsee処理されない文字に到達します正しい!

私はあなたの質問を正直に言い、ユニコードのシバン全体は有害であると考えるべきであり、私が見た(過去20年間)を除いて、すべての人が8ビットエンコーディングを使用すべきであると言います:恐ろしいさまざまなISO 8859エンコーディングのほか、キリル文字とEBCDICスイートで使用されているすべてのエンコーディングの混乱、そしてすべての障害のUnicodeはそれを上回っています。それが異なる国々の誤解の間のそれほど厄介な妥協ではなかったとしたら。

1
Donal Fellows