Representación unicode en java

Tengo una gran duda acerca de esto:

Tengo entendo que en java y tal vez en otros lenguajes de programación tiene la ventaja de manejar unicode...
Ejemplo:

byte b=126;  //esto en su representación unicode nos daría algo asi "~"

String unicodeB="";
String unicodeB=new String(new byte [] {b}); //esta es la linea que hace la conversion a unicode, según yo.

La duda es; Si por ejemplo yo tengo en b, un número negativo, ya que despues del 127, pasa a -128,-127, etc.

byte b=-115;
String unicodeB="";
String unicodeB=new String(new byte [] {b}); //el resultado da algo así "?".

Si yo hago el proceso inverso a esto, es decir si ese string lo vuelvo a byte, no me va a dar -115, sino 63, que es el número que representa "?". segun esta tabla http://unicode.coeurlumiere.com/

Este problema lo tengo, porque desde otra aplicación hecha en VB 5.0, estoy recibiendo una cadena que vienen estos valores. Por ejemplo: "€¡?" , donde el 5° elemento de la cadena, se que su valor no es 63, segun la tabla anterior.

Alguien puede explicarme esto por favor....Gracias.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

sigues confundido

No hay conversión directa entre bytes y unicode. Unicode es una codificación de texto, no de bytes crudos. Hay varios caracteres en Unicode cuya representación abarca de 2 a 4 bytes. Por eso existe UTF8 y UTF16 por ejemplo, en donde se indica el tamaño default de un caracter (UTF8 significa que un caracter por default mide 8 bits, y los caracteres que requieren 2 o más bytes tienen una codificación especial).

Si tienes un arreglo de bytes que leíste de un InputStream y lo quieres convertir a una cadena en Unicode, puedes crear la cadena con el constructor que recibe el arreglo de bytes y el nombre de la codificación:

byte[] loQueLeisteDelStream;
String cadena = new String(loQueLeisteDelStream, "UTF8");

En Java puedes manejar otras codificaciones. Hay una que se maneja por default, por ejemplo cuando creas una cadena a partir de un arreglo de bytes, sin indicar codificación. Eso depende de tu instalación de Java. Puedes conocerla con System.getProperty("file.encoding") y modificarla al iniciar tu aplicación con -Dfile.encoding=bla (donde bla por ejemplo puede ser UTF8).

Imagen de ezamudio

operación inversa

Ah y olvidaba la operación inversa. Si tienes una cadena, puedes obtener los bytes indicando la codificación correcta, por ejemplo cadena.getBytes("UTF8") en vez de simplemente cadena.getBytes().

Imagen de jtepetate

Agradezco tu respuesta

Agradezco me hayas explicado la duda sobre los bytes y unicode...en verdad.

Estoy comenzando apenas a trabajar con java, y hay cosas que aun no entiendo bien...

En la aplicación que estoy haciendo en Java, estoy recibiendo vía socket desde otra aplicación en VB, una cadena de cierto tamaño. Pero yo pensaba que el hecho de que llegaran así : por ejemplo;

....

BufferedReader entrada;
String mensaje;

entrada= new BufferedReader(new InputStreamReader(socket.getInputStream()));
mensaje=entrada.readLine();
....

pensaba que estaba convertido a unicode....pero en realidad, entonces tiene que ver con la codificación que tenga por default en mi sistema.
Es por ello que yo en la cadena "mensaje" recibo algo así:

System.out.println("mensaje recibido: "+mensaje);
// la salida es algo así, por ejemplo.

mensaje recibido: € ¬TvA

según la cadena que me hayan enviado...cierto??

Y por ejemplo, si la aplicación en VB espera un arreglo de 10 bytes, donde cada byte contiene información para que haga su propio proceso y me envie lo que le solicito. Ejemplo:

//este es el arreglo de bytes que espera la aplicación en VB, lo cual es normal, porque un byte va de 0 a 255. Pero en java no.
//en java es de -128 a 127.

[1,20,128,213,142,5,2,9,8,10] //esto es estático, siempre esperará estos valores...

cuando él recibe estos bytes, los procesa, y luego me contesta con otros 10 bytes, pero como cadena....lo que significa que recibiré estos bytes según la codificación de mi sistema.

Puede entonces variar el valor de los bytes de acuerdo al tipo de codificación de mi sistema, al momento de los quiera recibir de string a un arreglo de bytes???

Es decir, si recibo el arreglo de bytes como cadena:

System.out.println("mensaje recibido: "+mensaje);

//salida
mensaje recibido: € ¬TvA

y lo quisiera pasar a un arreglo de bytes de nuevo...?

Imagen de ezamudio

cadenas

Y por qué la conversión entre bytes y cadenas? Realmente necesitas manejar cadenas? estás esperando texto? Si realmente manejas arreglos de 10 bytes, por qué no manejar entonces arreglos de 10 bytes? es necesaria la conversión a cadena?

No puedes decir que la aplicación de VB te recibe bytes y te contesta una cadena. Imagina por un momento que la aplicación en VB es simplemente una caja negra. No sabes ni en qué fue escrita. Solamente envias bytes y recibes bytes. No sabes si dentro de la aplicación los convierten a cadena, y de hecho no importa. Lo que importa es lo que tienes que hacer tú con los datos que recibes de tu lado, y con lo que vas a enviar.

Para leer forzosamente Unicode de un stream, InputStreamReader tiene un constructor que recibe la codificación como parámetro adicional.

new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF8"));

Imagen de jtepetate

Gracias ezamudio

Entonces quieres decir que puedo enviar un arreglo de bytes de 10, tal como lo espera...

Por ejemplo:

byte arreglo={1,20,-128,30,22,34,56,-126,3,6};

y sabrá que ese -128 en realidad es un 128 ???, o ese -126 en realidad es un 130 ??

Además, quisiera preguntarte algo: Yo tengo entendido que si estoy trabajando con sockets con protocolo TCP, los mensajes que envio y/o recibo deben llegar completos, cierto???....es posible que los paquetes lleguen por partes, es decir de los 10 bytes que me envian, podría ser que me lleguen 8, y luego despues los otros dos???...porque algo similar me está pasando, pero no se a qué se deba. Gracias por ayudarme...

Imagen de ezamudio

sockets

Si quieres enviar byte por byte y estar seguro que envias por ejemplo un 128 o un 255, OutputStream tiene una variante del método write que recibe un entero. Ese entero debe ser entre 0 y 255; lo que hace es enviar ese valor como si fuera un byte sin signo (todo este rollo es porque en Java no tienes un tipo byte sin signo).

En TCP los mensajes que envias y recibes pueden llegar completos o incompletos. Para cosas cortas como un paquete de 10 bytes, lo más probable es que lleguen completos, sobre todo si ambos nodos están en la misma subred, pero si es a través de internet y pasas por varios routers pues entonces quién sabe si te van a llegar los 10 de golpe o si vas a recibir menos. Por eso los métodos de InputStream para lectura te indican cuántos bytes se leyeron.

Si esperas 10 bytes, puedes hacer un ciclo de 10 iteraciones leyendo un byte a la vez, o tener un buffer de 10 bytes y leer hasta que llegue todo:

byte[] buf = new byte[10];
//Byte por byte se lee asi
for (int i = 0; i < buf.length; i++) {
  buf[i] = (byte)stream.read();
  if (buf[i] == -1) { /* El stream ha sido cerrado, puedes arrojar una excepción o algo */ }
}
//Y asi puedes leer varios bytes, hasta tener todo completo
int pos = 0;
while (pos >= 0 && pos < buf.length) {
  int cuantos = stream.read(buf, pos, buf.length-pos);
  pos += cuantos;
  if (cuantos < 0) { pos = -1; /* El stream ha sido cerrado, podrías también arrojar una excepción */}
}
if (pos > 0) {
  //Leiste datos completos
} else {
  //leiste incompleto o tal vez nada
}

No debes confiar en que una sola llamada a InputStream.read te devuelva todo lo que estás esperando leer. Hay demasiadas variables impredecibles al momento de que llamas ese método como para que puedas estar seguro de que si esperas 10 bytes, te lleguen 10 bytes. Y cuando escribas al socket, recuerda siempre llamar OutputStream.flush() después de tus OutputStream.write() para que no se quede nada en buffers locales.

Imagen de jtepetate

Ok. Muchas gracias ezamudio

He hecho como me has dicho con el for, y sí logro recibir los bytes que se me envía. Te lo agradezco mucho.

Imagen de jtepetate

sockets en java

Tengo otra pregunta ezamudio...

En mi aplicación con sockets espero recibir varias secuencias de bytes, en este caso de 10 en 10.
Si tengo un InputStreamReader

InputStreamReader entrada= new InputStreamReader(socket.getInputStream());

byte []buffer=new byte[10];
                       
for(int i=0;i<buffer.length;i++){
                               
buffer[i]=(byte)en.read();
                               
}
                       

pero antes de recibir el siguiente, debo verificar que el primero sea el que espero (hago un algoritmo para ello), de no ser así, debo volver a pedirlo. Mi pregunta es: mientras estoy procesando el primer envio, el InputStreamReader estará guardando los envios que vayan llegando???. Cómo le hago para que pueda guardar en memoria varios envios ??. Supongamos que espero que en algunas ocaciones debo recir unos 500 a 1000 paquetes por segundos...

Gracias...

Imagen de ezamudio

threads

Si quieres leer del socket de manera independiente a la lectura, necesitas tener un hilo enviando datos y otro leyendo datos.

hola

tengo problemas con internacionalizacion . Recivo informacion del irc hispano estoy creando in clente de irc en java. Y no consigo ver ni los acentos ni ñ ni nada y no consigo solucionarlo por si fueras tan amable de ayudarme te dejo mi te dejo mi mail davidrovirosa@gmail.com.