2011-11-04 15 views
5

recibo de la toma de una cadena en una matriz de bytes que se parecen:¿Cómo detectar el final de la cadena en la matriz de bytes para la conversión de cadenas?

[128,5,6,3,45,0,0,0,0,0] 

El tamaño propuesta por el protocolo de red es la longitud total de la cadena (incluyendo ceros) por lo que, en mi exemple 10.

Si yo simplemente:

String myString = new String(myBuffer); 

tengo al final de la cadena de caracter 5 no correcta. La conversión no parece detectar el final del caracter de cadena (0).

para obtener el tamaño correcto y la cadena correcta hago esto:

int sizeLabelTmp = 0; 
//Iterate over the 10 bit to get the real size of the string 
for(int j = 0; j<(sizeLabel); j++) { 
    byte charac = datasRec[j]; 
    if(charac == 0) 
     break; 
    sizeLabelTmp ++; 
} 
// Create a temp byte array to make a correct conversion 
byte[] label = new byte[sizeLabelTmp]; 
for(int j = 0; j<(sizeLabelTmp); j++) { 
    label[j] = datasRec[j]; 
} 
String myString = new String(label); 

¿Hay una mejor manera de manejar el problema?

Gracias

Respuesta

7

0 no es un "carácter de fin de cadena". Es solo un byte. El hecho de que solo llegue al final de la cadena depende de la codificación que esté usando (y de lo que pueda ser el texto). Por ejemplo, si usó UTF-16, cada otro byte sería 0 para caracteres ASCII.

Si estás seguro de que el primer 0 indica el final de la cadena, puede utilizar algo como el código que has dado, pero me gustaría volver a escribir como:

int size = 0; 
while (size < data.length) 
{ 
    if (data[size] == 0) 
    { 
     break; 
    } 
    size++; 
} 

// Specify the appropriate encoding as the last argument 
String myString = new String(data, 0, size, "UTF-8"); 

I fuertemente recomendamos que no solo use la codificación predeterminada de la plataforma; no es portátil, y puede que no permita todos los caracteres Unicode. Sin embargo, no puede decidir arbitrariamente: debe asegurarse de que todo lo que produzca y consuma esta información concuerde con la codificación.

Si tiene el control del protocolo, sería mucho mejor si pudiera introducir un prefijo de longitud antes de la cadena, para indicar cuántos bytes hay en la forma codificada. De esa forma, usted podría leer exactamente la cantidad correcta de datos (sin "leer en exceso") y podría decir si los datos se truncaron por alguna razón.

+0

+1 para tomar la codificación en cuenta. Si las cosas recibidas sobre el socket son solo una serie Java serializada, debería estar bien. –

+0

@ G_H: "Solo una cadena de Java serializada" realmente no especifica cuál es el formato de serialización. Si el OP utilizara la serialización binaria de Java, no estaría haciendo esta operación explícitamente de todos modos ... y si se trata de algún otro formato de serialización, necesitaríamos saber * qué *. –

+0

Probablemente debería dejar de hablar ... El hecho es que siempre me he mantenido alejado de la serialización y no conozco muy bien los detalles. JAXB o JPA suele ser lo único que considero una opción. –

2

Las cadenas en Java no terminan con un 0, como en algunos otros idiomas. 0 se convertirá en el llamado carácter nulo, que puede aparecer en una Cadena. Sugiero que use algún esquema de recorte que detecte el primer índice de la matriz que es un 0 y usa una sub-matriz para construir la Cadena (suponiendo que todo lo demás será 0 después de eso), o simplemente construya la Cadena y llame al trim(). Eso eliminará el espacio en blanco inicial y final, que es cualquier carácter con código ASCII 32 o inferior.

Esto último no funcionará si tiene espacio en blanco inicial que debe conservar. Usar un StringBuilder y eliminar caracteres al final, siempre y cuando sean el carácter nulo, funcionaría mejor en ese caso.

2

Siempre puede comenzar al final de la matriz de bytes y retroceder hasta que llegue al primer valor distinto de cero. Luego solo copie eso en un nuevo byte y luego en String it. Espero que esto ayude:

byte[] foo = {28,6,3,45,0,0,0,0}; 
    int i = foo.length - 1; 

    while (foo[i] == 0) 
    { 
     i--; 
    } 

    byte[] bar = Arrays.copyOf(foo, i+1); 

    String myString = new String(bar, "UTF-8"); 
    System.out.println(myString.length()); 

Le dará un resultado de 4.

1

Me parece que está ignorando el recuento de lectura devuelto por el método read(). Es probable que los bytes nulos finales no se hayan enviado, es probable que todavía queden del estado inicial del búfer.

int count = in.read(buffer); 
if (count < 0) 
    ; // EOS: close the socket etc 
else 
    String s = new String(buffer, 0, count); 
+0

El buffer que se muestra en mi OP es solo un extracto de un paquete completo. La cadena se envía en medio del lote de otros datos. – grunk

+0

@grunk, entonces el protocolo debe decirle cuánto de él es la cadena, ya sea mediante la terminación nula o un prefijo de longitud. – EJP

9

Puede ser demasiado tarde, pero puede ayudar a otros. Lo más simple que puede hacer es new String(myBuffer).trim() que le proporciona exactamente lo que desea.

1

No profundizar en las consideraciones de protocolo que mencionó el OP original, ¿qué tal esto para recortar los ceros finales?

public static String bytesToString(byte[] data) { 
    String dataOut = ""; 
    for (int i = 0; i < data.length; i++) { 
     if (data[i] != 0x00) 
      dataOut += (char)data[i]; 
    } 
    return dataOut; 
} 
Cuestiones relacionadas