2011-06-30 14 views
5

Estoy tratando de leer datos de una secuencia binaria, partes de las cuales deben analizarse como UTF-8.Lea datos de texto y binarios de InputStream

Utilizando el InputStream directamente para los datos binarios y un InputStreamReader en la parte superior de la misma para el texto UTF-8 no funciona como el lector leerá adelante y estropear los datos binarios posteriores, incluso si se le dice que lea un máximo de n caracteres.

Reconozco que esta pregunta es muy similar a Read from InputStream in multiple formats, pero la solución propuesta allí es específica para las transmisiones HTTP, lo cual no me ayuda.

Pensé simplemente leer todo como datos binarios y luego convertir las piezas relevantes en texto. Pero solo tengo la información de longitud de los datos de caracteres en caracteres, no en bytes. Por lo tanto, necesito que lo que lee los caracteres de la secuencia sea consciente de la codificación.

¿Hay alguna manera de decirle a InputStreamReader que no lea más adelante de lo necesario para leer el número dado de caracteres? ¿O hay un lector que admita tanto datos binarios como texto con una codificación y se puede cambiar entre estos modos sobre la marcha?

Respuesta

2

Primero debe leer las partes binarias. Donde reconozca una porción de bytes que necesitan decodificación UTF-8, necesita extraer esos bytes y decodificarlos.

DataInputStream dis = 
// read a binary type. 
int num = dis.readInt(); 
int len = dis.readUnsignedShort(); 
// read a UTF-8 portion. 
byte[] bytes = new byte[len]; 
dis.readFully(bytes); 
String text = new String(bytes, "UTF-8"); 
// read some binary 
double d = dis.readDouble(); 
+1

El problema es que, con UTF8, el número de bytes puede ser diferente del número de caracteres. Así que necesitaría encontrar la cantidad de caracteres de múltiples bytes en la cadena, leer más bytes y convertir de nuevo, y hacer esto una y otra vez hasta que los números coincidan. – tajmahal

+0

Diría que su formato no es muy fácil de decodificar y que lo arreglaría si puede. Sin embargo, usted puede analizar el UTF-8 usted mismo si conoce la cantidad de caracteres. (Pero enviar el número real de bytes sería mucho más simple) –

+0

Otro enfoque es leer más datos de los necesarios. Tome la cantidad de caracteres esperados, p. substring() y convertir a UTF-8 para determinar la longitud. Usando mark() y reset() y lea la longitud que ahora conoce. (Esto solo funciona si la codificación UTF-8 es exactamente la misma: | por ejemplo, el byte nul \ 0 está codificado de dos maneras diferentes).(como pueden ser otros caracteres) –

2

Creo que simplemente no debe usar StreamReader. Los lectores tratan con el texto, pero usted trata el texto y los datos binarios juntos.

No hay manera. Debe leer los búfers binarios e interpretar su formato usted mismo, es decir, buscar la posición de los bytes de extracción de texto y transformarlos en Cadena.

Para simplificar esta tarea, le recomendaría crear su propia clase (digamos ProtocolRecord). Debería ser Serializable. Contendrá todos tus campos. Ahora tiene 2 opciones:

(1) simple: use el mecanismo de serialización de java. En este caso, solo tiene que ajustar la secuencia con DataInputStream para leer y DataOutputStream para escribir y luego leer/escribir sus objetos. La desventaja de este enfoque es que no puede controlar su protocolo.

(2) implemente los métodos readObject() y writeObject() usted mismo. Ahora use DataInputStream y DataOutputStream como se explicó anteriormente. En este caso, tiene que implementar el protocolo de serialización, pero al menos está encapsulado en su clase.

Cree que DataInputStream es lo que necesita.