2012-03-16 14 views
5

.NETで== `Encoding.UTF8.GetBytes(Encoding.UTF8.GetString(X))がありません:それは真実ではない理由はなぜX '

Encoding.UTF8.GetBytes(Encoding.UTF8.GetString(x)) 

は、元のバイト配列を返します任意のバイト配列x

別の質問にはmentionedですが、レスポンダは理由を説明しません。

+0

あなたはUTF-8ではなくASCIIについて話をするためのリンクです。 – svick

+1

'=='を使ってバイト配列を比較できますか?おそらく単に参照を比較するだけですから、配列の各要素を比較するループを作る必要があります。 – Matthew

+0

@Matthew [that answer](http://stackoverflow.com/a/3946274/85371)の要点は、エンコーディングが異なる可能性があると思われます。そして、例のコードには欠陥があります。 – sehe

答えて

1

文字エンコーディング(UTF8、具体的には)は、同じコードポイントに対して異なる形式を持つ場合があります。

文字列に変換して戻すとき、実際のバイトは異なる(正式な)形式を表す場合があります。

一部のUnicodeシーケンスは短所です:

String.Normalize(NormalizationForm.System.Text.NormalizationForm.FormD)

も参照してくださいを参照してください。これは同じ文字を表すためです。これらのいずれかが「A」を表すために使用することができるので、例えば、以下が等価であると考えられる:

"\u1EAF" 
"\u0103\u0301" 
"\u0061\u0306\u0301" 

しかし、順序、バイナリは、比較は、それらが異なるUnicodeコード値を含むので、これらの配列が異なる考慮されます。序数比較を実行する前に、アプリケーションはこれらの文字列を正規化して基本コンポーネントに分解する必要があります。

このページには、==は、配列の各要素を比較しませんので、これは常に正規化されているあなたはどのようなエンコーディング

+0

2つのメソッドのいずれかが文字列の形式を変更するのはなぜですか? – svick

+0

@svick私に尋ねないでください。私はそれができないことを保証するためにドキュメントをチェックしなかったが、 – sehe

+0

私はこれが起こらないと思う。これらの異なる形式は、さまざまなエンコーディングの性質ではなく、Unicode自体の性質であるためです。したがって、1文字はコードポイントの異なるシーケンスとして表現できます。しかし、コードポイントの単一のシーケンスは、特定のエンコーディングを使用する場合、バイトのシーケンスとして一方向にしか表現できません。 – svick

1

を示し素敵なサンプルが付属しています。 Encoding.UTF8との接続はありません。 チェックこの:watbywbarifが述べたように

var a = new byte[] { 1 }; 
var b = new byte[] { 1 }; 
bool res = a == b; 
3

まず、あなたは動作しませんので、==を使用して配列を比較するべきではありません。

しかし、配列を正しく比較しても(例えば、SequenceEquals()を使用するか、またはそれらを見るだけで)、配列は常に同じではありません。これが発生するケースは、xが無効なUTF-8エンコード文字列である場合です。

たとえば、0xFFの1バイトシーケンスは有効なUTF-8ではありません。だからEncoding.UTF8.GetString(new byte[] { 0xFF })は何を返しますか?それは 、U + FFFD、置換文字です。もちろん、Encoding.UTF8.GetBytes()に電話すると、0xFFは返されません。

+0

+1、私から素敵な例 – sehe

+1

私は 'SequenceEqual'拡張メソッドについて知りませんでした。 – PyreneesJim

1

Encodingクラスは往復のデータに設計さですが、それらは、旅行を丸めるように設計されているデータはbyteにエンコードcharデータ、ではなく、他の方法で回避されていることであるから、この時に来て別の角度。これが意味することは、Encodingの機能の中で、それぞれcharの値は、byteの値(1つ以上)に対応するエンコーディングを持ち、まったく同じの値に戻ります。 (これは、すべてのEncoding sがすべて可能char値については、これを行うことができないことは注目に値する - 例えば、は範囲[0, 128)char値をのみをサポートすることができます。)

だから、あなたは文字で開始している場合データを格納したり、バイト(ディスクやネットワークストリーム上のファイルなど)を扱うメディアに格納する方法が必要な場合は、charデータをbyteデータに変換してから違った終わり方。 (あなたはすべての可能文字列をサポートしたい場合は、あなたがそのようなEncoding.UnicodeEncoding.UTF8としてUnicodeベースEncoding S、のいずれかを使用する必要があります。)

だから、あなたが開始している場合、これは何を意味しています一束のbyte?さて、問題のエンコーディングによっては、実際にEncodingが出力するシーケンスではなく、実際に作業しているbyteがあるかもしれません。あなたはエンコーディング操作としてEncoding.GetBytesを見る必要があり、かつEncoding.GetChars/Encoding.GetStringデコード操作として、そしてあなたが任意のバイト配列から始まり、デコード彼らにしようとしています。

類推のために、画像のJPEGファイル形式を検討してください。これは、類似のタイプのをデコードします。この場合、デコードされたデータはstringではなく画像です。したがって、任意のバイト列を取ると、JPEG画像としてデコードできるチャンスは何ですか?それに対する答えは、明らかに非常にスリムです。おそらく、あなたのバイトは、「そこにいて、そのバイトが他のバイトに来るとは期待していませんでした」というデコーダのパスをたどり着くでしょう。そして、それは仮定のデータを扱うために最善を尽くしますそれは何とかダメージを受けた有効なJPEGファイルです。

任意のバイト配列を文字列に変換すると、まったく同じことが起こります。 UTF-8エンコーディングには、charの値128とそれ以上がエンコードされる方法に関する特定の規則があり、そのうちの1つは、110xxxxx,1110xxxxまたは11110xxxのようなパターンに一致するビットパターン10xxxxxxの後に、これはマルチバイトシーケンス(複数のbytesが単一のcharを表す)を「導入」します。したがって、あなたのデータに10xxxxxxというパターンに一致するバイトが含まれている場合、のいずれかになります。エンコーダは、データが何らかの形で損傷していると仮定することができます。それは何をするためのものか? 「エンコードされたデータに何かがひどく間違ってしまった」という文字が挿入されています。 Unicodeを設計した人々は、この正確なシナリオを予期し、この正確な意味を持つ文字を作成しました:Replacement Character。あなたがしようとしている場合

だから、char秒の文字列にあなたのbyte Sを往復し、このシナリオでは、問題byteの実際の値は失われ、代わりに置換文字が挿入され、検出されました。 stringbyteアレイに戻すと、元のデータではなく置換文字のエンコードが終了します。元のデータは失われます。

あなたが探しているのは、エンコード&という逆方向のデコード関係です。 Encodingcharのデータを取得し、一時的にデータをbyteというデータとして保存する方法です。 byteのデータを取得し、それを一時的にcharデータとして保存するには、その特定の目的に合わせて設計されたエンコーディングが必要です。幸いにも、これらは存在します。 Wikipediaにはオプションのfairly comprehensive listがあります。 :-)

.NET Framework内では、最も簡単で最もアクセスしやすいオプションは、MIME Base-64エンコードで、Convert.ToBase64StringConvert.FromBase64Stringで公開されています。

関連する問題