这将是如此明显,但为什么这会失败?

时间:2011-01-22 18:26:04

标签: c# .net

已经编码.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的答案。可以在他的答案中读取16个字节的原因,即32个字节。答案中也说明了:

  

的默认构造函数   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);

3 个答案:

答案 0 :(得分:6)

并非每个字节序列都是有效的UTF-8编码字符串。

GUID几乎可以包含任何字节序列。但是UTF-8作为特定规则,如果值> 127,则允许字节序列。 Guid通常不会遵循这些规则。

然后,当您将损坏的字符串编码回字节数组时,您将得到一个长度超过16个字节的字节数组,Guid的构造函数不接受。


UTF8Encoding.GetString的文档声明:

  

使用错误检测时,无效序列会导致此方法抛出ArgumentException。如果没有错误检测,将忽略无效序列,并且不会抛出异常。

并且UTF8Encoding的默认构造函数已禁用错误检查(不要问我原因)。

  

此构造函数创建一个不提供Unicode字节顺序标记的实例,并且在检测到无效编码时不会引发异常。
  注意
  出于安全原因,建议您的应用程序使用接受throwOnInvalidBytes参数的构造函数并将该参数设置为true来启用错误检测。


您可能希望使用Base64编码而不是UTF-8。这样,您可以将任何有效的字节序列映射到字符串中并返回。

答案 1 :(得分:3)

要将任意字节数据编码为字符串,您应该使用base-64,hex等。您不能假设随机字节集产生有效的UTF *(或其他编码)字符串。

http://marcgravell.blogspot.com/2010/03/binary-data-and-strings.html

答案 2 :(得分:0)

因为var b是类型string,这意味着它是一个unicode字符串(每个字符2个字节)。在第二行中,您将从16字节数组中创建一个16个字符的字符串,但该16个字符的字符串以32个字节存储。

为什么不这样做:

var d = Guid.NewGuid();