2009-09-14 18 views
19

Así que este es el trato: estoy tratando de abrir un archivo (desde bytes), convertirlo en una cadena para que pueda meter algunos metadatos en el encabezado, convertirlo de nuevo a bytes, y guardarlo. El problema con el que me estoy metiendo ahora es con este código. Cuando comparo la secuencia que ha sido convertida de ida y vuelta (pero no modificada) a la matriz de bytes original, es desigual. ¿Cómo puedo hacer que esto funcione?Convirtiendo matriz de bytes a cadena y viceversa en C#

public static byte[] StringToByteArray(string str) 
{ 
    UTF8Encoding encoding = new UTF8Encoding(); 
    return encoding.GetBytes(str); 
} 

public string ByteArrayToString(byte[] input) 
{ 
    UTF8Encoding enc = new UTF8Encoding(); 
    string str = enc.GetString(input); 
    return str; 
} 

Así es como los estoy comparando.

byte[] fileData = GetBinaryData(filesindir[0], Convert.ToInt32(fi.Length)); 
string fileDataString = ByteArrayToString(fileData); 
byte[] recapturedBytes = StringToByteArray(fileDataString); 
Response.Write((fileData == recapturedBytes)); 

estoy seguro de que es UTF-8, usando:

StreamReader sr = new StreamReader(filesindir[0]); 
Response.Write(sr.CurrentEncoding); 

que devuelve "System.Text.UTF8Encoding".

+6

¿está seguro de que es su UTF-8 para empezar? –

+0

No estoy seguro. ¿Cómo podría decir si es o no? –

+0

¿Qué quieres decir con que es desigual? ¿Tu cuerda es desigual? no obtienes el mismo resultado de cadena? – Khan

Respuesta

16

Pruebe las funciones estáticas en la clase Encoding que le proporciona ejemplos de varias codificaciones. No debería necesitar crear una instancia del Encoding solo para convertir a/desde un conjunto de bytes. ¿Cómo comparas las cuerdas en el código?

Editar

Usted está comparando las matrices, no cadenas. Son desiguales porque se refieren a dos matrices diferentes; utilizando el operador == solo compararán sus referencias, no sus valores. Tendrá que inspeccionar cada elemento de la matriz para determinar si son equivalentes.

public bool CompareByteArrays(byte[] lValue, byte[] rValue) 
{ 
    if(lValue == rValue) return true; // referentially equal 
    if(lValue == null || rValue == null) return false; // one is null, the other is not 
    if(lValue.Length != rValue.Length) return false; // different lengths 

    for(int i = 0; i < lValue.Length; i++) 
    { 
     if(lValue[i] != rValue[i]) return false; 
    } 

    return true; 
} 
+0

He editado la pregunta para mostrar cómo ... ¡el código no aparece en el comentario! –

+0

Intenté esto, me devuelven que no son de la misma longitud. Debe estar en otro lugar. –

+3

Eche un vistazo a la documentación para la codificación UTF8. Existe la opción de especificar o no el preámbulo. Si descubres que tu matriz de bytes generada es más larga que la original, es probable que sea tu problema. De nuevo, debe asegurarse de que UTF8 sea, de hecho, la codificación correcta. En cuanto a cómo puedes saber, deberías preguntarle a quien te está entregando la información. –

3

Su problema parece ser la forma en que está comparando la matriz de bytes:

Response.Write((fileData == recapturedBytes)); 

resultado siempre será falsa, ya que está comparando la dirección de la matriz de bytes, no el valores que contiene. Compare los datos de cadena, o use un método para comparar las matrices de bytes. También puede hacer esto en su lugar:

Response.Write(Convert.ToBase64String(fileData) == Convert.ToBase64String(recapturedBytes)); 
5

Debido al hecho de que las cadenas de .NET utilizan cadenas Unicode, ya no se puede hacer a este pueblo como lo hicieron en C. En la mayoría de los casos, ni siquiera debería intento de ir y venir desde la cadena < -> array de bytes a menos que el contenido sea en realidad texto.

tengo que aclarar este punto: En .NET, si los datos no es byte[] texto, entonces no intente convertirlo en un string excepto por el especial Base64 codificación de los datos binarios a través de un texto canal. Este es un malentendido ampliamente difundido entre las personas que trabajan en .NET.

+4

Cadena <-> byte [] las conversiones generalmente se deben realizar a través de una de las clases System.Text.Encoding, no de la clase BitConverter. BitConverter.ToString convierte una matriz de bytes en una representación de cadena hexadecimal de los números, ** ** no convierte una matriz de bytes en una cadena. –

+1

Heh, debería haber eliminado esa línea una vez que sabía que no era el objetivo de mi publicación. –

7

Cuando tenga bytes primas (8 bits personajes posiblemente no-imprimibles) y quiere manipularlos como una cadena NET y convertirlos de nuevo en bytes, puede hacerlo utilizando

Encoding.GetEncoding(1252) 

en lugar de UTF8Encoding. Esa codificación funciona para tomar cualquier valor de 8 bits y convertirlo en .NET de 16 bits, y viceversa, sin perder ninguna información.

En el caso específico que describe arriba, con un archivo binario, no podrá "meterse con metadatos en el encabezado" y hacer que las cosas funcionen correctamente a menos que la longitud de los datos con los que se mezcla no cambie. Por ejemplo, si el encabezado contiene

{any}{any}ABC{any}{any} 

y desea cambiar a ABC DEF, que debería funcionar como desee. Pero si quiere cambiar ABC a WXYZ, tendrá que escribir sobre el byte que sigue a "C" o lo hará (en esencia) mover todo un byte más hacia la derecha. En un archivo binario típico, eso ensuciará mucho las cosas.

Si los bytes después de "ABC" son espacios o caracteres nulos, existe una mayor probabilidad de que escribir datos de reemplazo más grandes no cause problemas, pero aún no puede reemplazar ABC con WXYZ en la cadena .NET, haciéndolo más largo - Tendría que reemplazar ABC {whatever_follows_it} con WXYZ. Dado eso, puede encontrar que es más fácil simplemente dejar los datos como bytes y escribir los datos de reemplazo un byte a la vez.

+0

Si uno tiene una matriz de bytes y desea reemplazar todas las ocurrencias de una secuencia particular con otra secuencia de una longitud diferente (por ejemplo, reemplazar todas las ocurrencias de {0x7D, 0x5E} con {0x7E}), se convertiría a cadena, usando 'String .Replace', y luego convertir de nuevo un enfoque razonable? ¿La codificación mencionada anteriormente reemplazaría cada valor de byte 0-255 con su código correspondiente con el mismo número [el hecho de que la codificación sea sin pérdida no implicaría por sí mismo eso]? – supercat

+0

@supercat - Sí, ese enfoque (siempre que utilice la codificación 1252) funcionaría. Pero aún no podrá hacer eso con la mayoría de los formatos de archivo binarios por las razones mencionadas en mi mensaje. –

+0

Si uno está usando formatos sensibles a la posición, uno obviamente tendría que asegurarse de que las cosas que no deberían moverse, no lo hacen. Incluso entonces, habría casos en los que 'String.Replace' parecería útil si las cadenas "original" y "de reemplazo" tienen la misma longitud. – supercat

Cuestiones relacionadas