2011-01-22 6 views
6

何年も前に.netをコーディングしていましたが、n00bのように感じます。次のコードが失敗するのはなぜですか?それははっきりしているはずですが、なぜこれは失敗しますか?

byte[] a = Guid.NewGuid().ToByteArray(); // 16 bytes in array 
string b = new UTF8Encoding().GetString(a); 
byte[] c = new UTF8Encoding().GetBytes(b); 
Guid d = new Guid(c); // Throws exception (32 bytes recived from c) 

アップデートはCodeInChaosからの回答を承認しました。彼の答えでは、32バイトになる16バイトの理由を読み取ることができます。また、その答えに次のように述べた。

UTF8Encodingのデフォルトコンストラクタは無効なバイトを含む文字列をバイト配列をエンコードしようとすると、UTF8エンコーダが例外をスローする必要私見 無効

エラーチェックがあります。 .netフレームワークが適切に動作するようにするには、次のようにコードを記述する必要があります。

byte[] a = Guid.NewGuid().ToByteArray(); 
string b = new UTF8Encoding(false, true).GetString(a); // Throws exception as expected 
byte[] c = new UTF8Encoding(false, true).GetBytes(b); 
Guid d = new Guid(c); 
+1

「var」を削除していただきありがとうございます。まるで 'var'の全体がエラーを隠すようになっているかのようです。 :) – MusiGenesis

答えて

6

すべてのバイトシーケンスが有効なUTF-8エンコード文字列であるとは限りません。

GUIDには、ほとんどすべてのバイトシーケンスを含めることができます。しかし、値が127より大きい場合、バイトシーケンスが許可される特定の規則としてのUTF-8。そして、Guidはこれらのルールに従わないことがよくあります。

その後、破損した文字列をバイト配列にエンコードすると、Guidのコンストラクタが受け入れない16バイトより長いバイト配列が取得されます。


UTF8Encoding.GetString上のドキュメントは述べている:エラー検出で

、無効なシーケンスは、ArgumentExceptionがスローをするために、このメソッドが発生します。エラー検出がなければ、無効なシーケンスは無視され、例外はスローされません。

デフォルトのUTF8Encodingコンストラクタでは、エラーチェックが無効になっています(理由はわかりません)。

このコンストラクタは、Unicodeバイトオーダーマークを提供しないインスタンスを作成し、無効なエンコーディングが検出されたときに例外をスローしません。

セキュリティ上の理由から、throwOnInvalidBytesパラメータを受け入れ、そのパラメータをtrueに設定するコンストラクタを使用してエラー検出を有効にすることをお勧めします。


かわりに、UTF-8のBase64エンコードを使用する場合があります。そうすれば、有効なバイトシーケンスを文字列にマップして戻すことができます。

+0

UTF8でエンコードできない文字列を受け取ったときに、フレームワークが例外をスローしないのはなぜですか? –

+1

なぜ彼らはそのようなAPIを設計したのか分かりません。 IMOは、デフォルトでエンコーディングエラーを静かに無視するのは愚かです。 – CodesInChaos

0

var bはタイプstringです。つまり、ユニコード文字列(1文字あたり2バイト)です。 2行目では、16バイトの配列から16文字の文字列を作成しますが、その16文字の文字列は32バイトに格納されます。

理由だけでこれをしない:

var d = Guid.NewGuid(); 
+0

明らかに、文字列「b」は送信または格納され、次に別の場所でデコードされます。後で直接デコードが行われるのは、これが問題を実証する簡単なサンプルコードだからです。 – CodesInChaos

関連する問題