2011-01-22 25 views
6

Ha estado codificando .net desde hace años pero me siento como un n00b. ¿Por qué falla el siguiente código?Debería ser tan obvio, pero ¿por qué no funciona?

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) 

actualización

Aprobada la respuesta de CodeInChaos. La razón de los 16 bytes que se convierten en 32 bytes se puede leer en su respuesta. También se indica en la respuesta:

el constructor por defecto de UTF8Encoding tiene comprobación de errores discapacitados

mi humilde opinión el codificador UTF-8 debe lanzar una excepción cuando se trata de codificar una matriz de bytes en cadena que contiene bytes no válidos. Para hacer el marco .NET comportarse adecuadamente el código debe haber sido escrito de la siguiente manera

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

Gracias por deshacerse de 'var'. Es como si todo el punto de 'var' fuera a ocultar errores. :) – MusiGenesis

Respuesta

6

No todos secuencia de bytes es una cadena codificada en UTF-8 válidos.

El GUID puede contener casi cualquier secuencia de bytes. Pero UTF-8 como reglas específicas para las cuales se permiten secuencias de bytes si el valor es> 127. Y un Guid a menudo no seguirá estas reglas.

Luego, cuando codifica la cadena dañada de nuevo a una matriz de bytes, obtiene una matriz de bytes de más de 16 bytes, que el constructor de Guid no acepta.


La documentación sobre UTF8Encoding.GetString afirma:

Con la detección de errores, una secuencia no válida hace que este método para lanzar una ArgumentException. Sin detección de errores, se ignoran las secuencias no válidas y no se lanza ninguna excepción.

y el constructor predeterminado de UTF8Encoding ha desactivado la comprobación de errores (no me pregunte por qué).

Este constructor crea una instancia que no proporciona una marca de orden de bytes Unicode y no arroja una excepción cuando se detecta una codificación no válida.
Nota
Por razones de seguridad, se recomienda que sus aplicaciones habiliten la detección de errores utilizando el constructor que acepta un parámetro throwOnInvalidBytes y establezca ese parámetro en verdadero.


Es posible que desee utilizar la codificación Base64 en lugar de UTF-8. De esta forma, puede asignar cualquier secuencia de bytes válida a una cadena y viceversa.

+0

Entonces, ¿por qué el framework no lanza una excepción cuando recibe una cadena que no puede codificar UTF8? –

+1

No hay idea de por qué diseñaron su API así. La IMO ignora silenciosamente los errores de codificación por defecto es estúpido. – CodesInChaos

0

Porque var b es tipo string, lo que significa que es una cadena Unicode (2 bytes por carácter). En su segunda línea, está creando una cadena de 16 caracteres de una matriz de 16 bytes, pero esa cadena de 16 caracteres se almacena en 32 bytes.

¿Por qué no hacer esto:

var d = Guid.NewGuid(); 
+0

Obviamente, la cadena 'b' se transmitirá o almacenará y luego se decodificará en otra parte. Que la descodificación ocurra directamente después es solo porque este es un código de muestra simple que demuestra el problema. – CodesInChaos

Cuestiones relacionadas