2008-08-21 17 views
27

Tengo datos binarios en un archivo que puedo leer en una matriz de bytes y procesar sin ningún problema. Ahora necesito enviar partes de los datos a través de una conexión de red como elementos en un documento XML. Mi problema es que cuando convierto los datos de una matriz de bytes a una Cadena y vuelvo a una matriz de bytes, los datos se corrompen. He probado esto en una máquina para aislar el problema de la conversión de cadena, así que ahora sé que no se está corrompiendo con el analizador XML o el transporte de red.¿Cómo se convierten datos binarios a cadenas y viceversa en Java?

Lo que tengo en este momento es

byte[] buffer = ...; // read from file 
// a few lines that prove I can process the data successfully 
String element = new String(buffer); 
byte[] newBuffer = element.getBytes(); 
// a few lines that try to process newBuffer and fail because it is not the same data anymore 

¿Alguien sabe cómo convertir binario a cuerdas y volver sin pérdida de datos?

Respondido: Gracias Sam. Me siento como un idiota. Ayer respondí esto porque mi analizador SAX se quejaba. Por alguna razón, cuando me encontré con este tema aparentemente separado, no se me ocurrió que era un nuevo síntoma del mismo problema.

EDIT: Sólo por el bien de la exhaustividad, utiliza la clase Base64 del paquete Apache CommonsCodec para resolver este problema.

Respuesta

19

Si codifica en base 64, esto resultará ningún datos en ASCII de texto seguro, pero los datos codificados en base64 es más grande que los datos orignal

0

Cómo estás construyendo su documento XML? Si utiliza las clases XML integradas de Java, entonces la codificación de cadena se debe manejar por usted.

Eche un vistazo a los paquetes javax.xml y org.xml. Eso es lo que usamos para generar documentos XML, y maneja toda la codificación y decodificación de cadenas bastante bien.

--- EDIT:

Hmm, creo que no he entendido bien el problema. ¿No estás tratando de codificar una cadena normal, sino un conjunto de datos binarios arbitrarios? En ese caso, la codificación Base64 sugerida en un comentario anterior es probablemente el camino a seguir. Creo que es una forma bastante estándar de codificación de datos binarios en XML.

2

Ver esta pregunta, How do you embed binary data in XML? En lugar de convertir el byte [] en cadena luego empujando en XML en algún lugar, convertir el byte [] en una cadena a través de la codificación Base64 (algunas librerías XML tienen un tipo de hacer esto para usted). La decodificación BASE64 una vez que recuperas el String de XML.

Uso http://commons.apache.org/codec/

sus datos se puede conseguir en mal estado debido a todo tipo de restricciones de juego de caracteres extraños y la presencia de caracteres no priting. Stick w/BASE64.

35

String(byte[]) trata los datos como la codificación de caracteres predeterminada. Entonces, cómo se convierten los bytes de los valores de 8 bits a los caracteres de Java Unicode de 16 bits variará no solo entre los sistemas operativos, sino que incluso puede variar entre diferentes usuarios que utilizan diferentes páginas de códigos en la misma máquina. Este constructor solo sirve para decodificar uno de tus propios archivos de texto. ¡No intente convertir bytes arbitrarios a caracteres en Java!

La codificación como base64 es una buena solución. Así es como los archivos se envían a través de SMTP (correo electrónico). El proyecto (gratuito) Apache Commons Codec hará el trabajo.

byte[] bytes = loadFile(file);   
//all chars in encoded are guaranteed to be 7-bit ASCII 
byte[] encoded = Base64.encodeBase64(bytes); 
String printMe = new String(encoded, "US-ASCII"); 
System.out.println(printMe); 
byte[] decoded = Base64.decodeBase64(encoded); 

Alternativamente, se puede utilizar el Java 6 DatatypeConverter:

import java.io.*; 
import java.nio.channels.*; 
import javax.xml.bind.DatatypeConverter; 

public class EncodeDecode {  
    public static void main(String[] args) throws Exception { 
    File file = new File("/bin/ls"); 
    byte[] bytes = loadFile(file, new ByteArrayOutputStream()).toByteArray(); 
    String encoded = DatatypeConverter.printBase64Binary(bytes); 
    System.out.println(encoded); 
    byte[] decoded = DatatypeConverter.parseBase64Binary(encoded); 
    // check 
    for (int i = 0; i < bytes.length; i++) { 
     assert bytes[i] == decoded[i]; 
    } 
    } 

    private static <T extends OutputStream> T loadFile(File file, T out) 
                 throws IOException { 
    FileChannel in = new FileInputStream(file).getChannel(); 
    try { 
     assert in.size() == in.transferTo(0, in.size(), Channels.newChannel(out)); 
     return out; 
    } finally { 
     in.close(); 
    } 
    } 
} 
Cuestiones relacionadas