Foros del Web » Programación para mayores de 30 ;) » Java »

Problema con Stream en Java

Estas en el tema de Problema con Stream en Java en el foro de Java en Foros del Web. Hola a todos, necesito vuestra ayuda, el caso es que tengo que hacer un aplicación cliente servidor, y para enviar datos de un fichero del ...
  #1 (permalink)  
Antiguo 08/02/2010, 14:33
 
Fecha de Ingreso: junio-2009
Mensajes: 65
Antigüedad: 14 años, 10 meses
Puntos: 0
Problema con Stream en Java

Hola a todos, necesito vuestra ayuda, el caso es que tengo que hacer un aplicación cliente servidor, y para enviar datos de un fichero del cliente al servidor, me he creado un clase Datos, en la cual, tienes un buffer de bytes de 1024, mas la longitud rellena del buffer.

Bien esa clase es serializable, pero tengo un problema, el enviarla con writeObject(datos) siendo datos una clase Serializable, cada vez que leo en cliente datos, coloco la nueva longitud con el metodo set de la clase Datos, hasta el final de fichero que será 0.

El problema que tengo que los datos leidos del buffer, es decir, del array de datos, si que los sobreescribe dado a que en la clase datos coloco el .clone()

La clase datos es la siguiente:

Código:
package Mensajes;

import java.io.Serializable;
public class Datos implements Serializable{

			/**
	 * 
	 */
	private static final long serialVersionUID = -2098453470046067754L;
			private byte [] datos;
			private int longitud;
			private int md5;
			
			public Datos ()
			{
				this.datos = new byte[1024];
				this.longitud=0;
			}
			
			public void setDatos(byte [] pdatos)
			{
				this.datos=pdatos.clone();
			}
			public byte [] getDatos()
			{
				return this.datos;
			}
			public void setLongitud(int plongitud)
			{
				this.longitud= plongitud;
			}
			public int getLongitud()
			{
				return longitud;
			}
}
Mientras que el codigo del envio del cliente es el siguiente:

Código:
		public static void enviar_fichero(ObjectOutputStream entrada, String dir_local,File fichero)
		{
			try {
	            // Me pongo a leer fichero y enviar.
	            int len;
	            byte [] buffer_aux = new byte[1024];
	            FileInputStream lectura_fich = new FileInputStream(fichero);
	             Datos mis_datos = new Datos();
	            while ((len = lectura_fich.read(buffer_aux)) > 0) 
	            {
	               mis_datos.setDatos(buffer_aux);
	               mis_datos.setLongitud(len);
	               System.out.println("LEIDOS: "+mis_datos.getLongitud());
	               entrada.writeObject(mis_datos);
	               entrada.flush();
	            }
	            mis_datos.setDatos(buffer_aux);
	            mis_datos.setLongitud(len);
	            entrada.writeObject(mis_datos);
	            entrada.flush();
	            lectura_fich.close();
			} catch (IOException e) {
				System.out.println("Cli# ERROR: Problema al leer o escribir en la conexión. (Enviar fichero)");
			}
		}

Y la recepcion del servidor lo hace de la siguiente forma:

Código:
try {
					File fichero_disco = new File (dir_local+"/"+fichero_nombre);
					FileOutputStream f_out = new FileOutputStream(fichero_disco);
	
			        byte[] buf_aux = new byte[1024];
			        int len;
			        Datos recibido = (Datos)salida_objetos.readObject();
			        while ((len=recibido.getLongitud()) > 0) {
			        	System.out.println("RECIBIDO LONGITUD: "+len);
			            f_out.write(recibido.getDatos(), 0, len);
			            recibido = (Datos)salida_objetos.readObject();
			        }
			        System.out.println("RECIBIDO LONGITUD FINNN: "+recibido.getLongitud());
				    f_out.close();
				    System.out.println("Ser# Fichero enviado con éxito.");
				} catch (ClassNotFoundException e)
				{
					System.out.println("Ser# Problema al convertir objeto");
				} catch (FileNotFoundException e) {
					System.out.println("Ser# Problema al convertir objeto");
				} catch (IOException e) {
					System.out.println("Ser# ERROR: Problema al leer o escribir en la conexión.");
				}
Espero que me puedan ayudar, si necesitan alguna información más para ayudarme.

Muchas Gracias!
  #2 (permalink)  
Antiguo 08/02/2010, 16:14
 
Fecha de Ingreso: junio-2009
Mensajes: 65
Antigüedad: 14 años, 10 meses
Puntos: 0
Respuesta: Problema con Stream en Java

Estoy haciendo esta prueba y tampoco funciona:

Servidor:

Código:
package Servidor;

import java.net.*;
import java.io.*;
public class Ser {

	
			public static void main (String args[])
			{
				ServerSocket ser;
				try {
					ser = new ServerSocket(2000);
				System.out.println("Conectado:");
				Socket cli = ser.accept();
				
				ObjectInputStream salida = new ObjectInputStream (cli.getInputStream());
				
				Prueba p=null;
				try {
					p = (Prueba)salida.readObject();
				} catch (ClassNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("RECIBIDO: "+p.getNum());
				System.out.println("RECIBIDO: "+p.getNum());
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
}
Clase Prueba:
Código:
package Servidor;
import java.io.Serializable;
public class Prueba implements Serializable{

		private int num;
		
		public Prueba(int pnum)
		{
			this.setNum(pnum);
		}

		public void setNum(int num) {
			this.num = num;
		}

		public int getNum() {
			return num;
		}
}
Cliente:

package Cliente;
Código:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.*;

import Servidor.Prueba;
public class Cli {

			
			public static void main (String args[])
			{
					Socket s;
					try {
						s = new Socket("127.0.0.1",2000);

					ObjectOutputStream entrada = new ObjectOutputStream (s.getOutputStream());
					System.out.println("Conectado correctamente...");
					Prueba p = new Prueba(5);
					System.out.println("Enviando...");
					entrada.writeObject(p);
					p.setNum(10);
					entrada.writeObject(p);
					
					} catch (UnknownHostException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
			}

}
  #3 (permalink)  
Antiguo 08/02/2010, 22:59
Avatar de HackmanC  
Fecha de Ingreso: enero-2008
Ubicación: Guatemala
Mensajes: 1.817
Antigüedad: 16 años, 2 meses
Puntos: 260
Sonrisa Respuesta: Problema con Stream en Java

Hola,

Posiblemente ... resetea el ObjectInputStream después de cada escritura.

entrada.writeObject(p);
entrada.reset();

Al parecer el ObjectInputStream mantiene un cache de los objetos que se serializan y no detecta cambios en los objetos.

Mi primer idea fue escribir objetos diferentes pero al parecer se producen errores de memoria, puesto que el cache crece por cada objeto que se serializa y el garbage collector no le da tiempo de borrarlos o no los elimina porque el Stream tiene una referencia pendiente o algo parecido.

Ahora bien ... por qué no envías el archivo directamente con un Stream, sin necesidad de serializar un objeto que contiene parte del archivo usando ObjectInputStream?

Saludos,
  #4 (permalink)  
Antiguo 09/02/2010, 11:31
 
Fecha de Ingreso: junio-2009
Mensajes: 65
Antigüedad: 14 años, 10 meses
Puntos: 0
Respuesta: Problema con Stream en Java

Hola, en primer lugar muchas gracias por contestar a mi problema.
Lo del resetear el Stream cada vez que envio un objeto no lo habia probado, ahora no estoy en casa, cuando llegue lo pruebo y comento a ver si puede que funcione.

En cuánto a crear la clase y no enviarlo directamente, no se a lo que te refieres, si te refieres a utilizar solemente el OuputStream con la opcion de write(byte[],off,len); no lo hago asi, por que pensaba que hacerlo enviado un objeto me iba a ser mas fácil.

De todas maneras probe de esa forma, y tambien me daba error, al recibir el último 0!

Probare a resetear el stream, una pregunta esa operacion, solamente resetea el stream, pero no cierra la conexión, no?

¿Que es realmente lo que hace? ¿Más o menos como un flush, o que es lo que hace?

Muchas Gracias!
  #5 (permalink)  
Antiguo 09/02/2010, 21:24
Avatar de HackmanC  
Fecha de Ingreso: enero-2008
Ubicación: Guatemala
Mensajes: 1.817
Antigüedad: 16 años, 2 meses
Puntos: 260
Sonrisa Respuesta: Problema con Stream en Java

Hola,

Posiblemente ... el método reset() debería inicializar un stream hasta el principio del mismo, pero hay stream's que no se pueden resetear o hace algo diferente. Cualquier clase heredada de la clase stream lo puede reescribir de forma diferente.

Por ejemplo, en un File Stream debería poner el lector del File al inicio del mismo otra vez, sin importar si leiste ya una parte del mismo, pero en otro tipo de Stream no se puede 'volver al inicio', así que lo usan de forma diferente.

En el caso del ObjectOutputStream al parecer borra un cache interno que mantiene una copia de todos los objetos que se serializan. Esa copia se mantiene para no tener que enviar el objeto varias veces.

Por ejemplo, en la forma que está tu programa actualmente, si mandas el objeto un millón de veces lo va a realizar en unos cuantos segundos, puesto que no manda el objeto de nuevo, solamente un indicador que el objeto enviado anteriormente se volvío a enviar, e indica que debe usar el que está en caché, para ahorrar ancho de banda en la red ... posiblemente.

El método reset() no cierra la conexión.

Saludos,
  #6 (permalink)  
Antiguo 09/02/2010, 21:59
Avatar de HackmanC  
Fecha de Ingreso: enero-2008
Ubicación: Guatemala
Mensajes: 1.817
Antigüedad: 16 años, 2 meses
Puntos: 260
Sonrisa Respuesta: Problema con Stream en Java

Hola,

Cita:
Iniciado por moisesvs Ver Mensaje
... En cuánto a crear la clase y no enviarlo directamente, no se a lo que te refieres, si te refieres a utilizar solemente el OuputStream con la opcion de write(byte[],off,len); no lo hago asi, por que pensaba que hacerlo enviado un objeto me iba a ser mas fácil. ...
No creo que sea más difícil y es mucho mejor si usas un Buffered Stream. El objetivo de un Object Stream es enviar un objeto con métodos y propiedades, y tiene un objetivo muy diferente, lo que intentas hacer es enviar datos.

Creo que enviar un objeto tiene una penalización en desempeño muy alta, cada vez que envias el objeto se tiene que crear en el cliente y en el servidor, y para crear un objeto el VM de java trabaja mucho.

Enviar solo los datos va a ser mucho más eficiente, si realmente no tienes otro objetivo por el cual necesites serializar un objeto.

Saludos,
  #7 (permalink)  
Antiguo 10/02/2010, 12:00
 
Fecha de Ingreso: junio-2009
Mensajes: 65
Antigüedad: 14 años, 10 meses
Puntos: 0
Respuesta: Problema con Stream en Java

Hola muchas gracias por contestar!

Ayer por la tarde estuve revisando el código, y estuve viendo lo de resetear el Stream! y funciona! perfectamente.

La verdad es que me ha estrañado un poco esto del buffer por que nunca me habia pasado, pero en realidad funciona bastante bien, no entiendo por que Java no se fija en OID de cada objeto que se genera en la clase para ver si enviar un objeto o no.

Dado a que enviar un objeto, cambiar su estado y volverlo a enviar debe de ser bastante común... pero bueno problema solucionado, y por lo menos he aprendido que Java cachea por referencia a memoria.

En cuánto a lo otro que me comentas, lo hago asi en una clase, por que aparte tengo que enviar datos cifrados, es decir, sistema de cifrado de MD5, para comprobar los datos, de esta forma en una clase es mas rápido, por esa razón, la clase Datos tienen los datos del MD5 tambien.

Saludos y muchas gracias!
  #8 (permalink)  
Antiguo 10/02/2010, 23:43
Avatar de HackmanC  
Fecha de Ingreso: enero-2008
Ubicación: Guatemala
Mensajes: 1.817
Antigüedad: 16 años, 2 meses
Puntos: 260
Sonrisa Respuesta: Problema con Stream en Java

Hola,

Que bueno que hayas resuelto el problema, solamente me gustaría agregar un comentario que posiblemente te sea de utilidad,

Cita:
Iniciado por moisesvs Ver Mensaje
... y por lo menos he aprendido que Java cachea por referencia a memoria. ...
Básicamente, yo no conozco otra clase, aparte del Object Stream, donde se haga un cache de los objetos automáticamente; debería estar mejor documentado porque me pareció algo muy diferente a como funciona Java.

Saludos,
  #9 (permalink)  
Antiguo 16/02/2010, 17:28
 
Fecha de Ingreso: junio-2009
Mensajes: 65
Antigüedad: 14 años, 10 meses
Puntos: 0
Respuesta: Problema con Stream en Java

Una vez solucionado el problema que tuve, tengo otro problema, que creo que tambien es otro "problema" que ocurre solamente con Java, en este caso, se trata a la hora de coger los Stream del servidor o el cliente, es decir:

Servidor:

Coge el INPUT
Coge el OUTPUT

Cliente:

Coge el INPUT
Coge el OUTPUT

Y da un problema, es decir, no da ninguna excepcion ni nada, solamente se queda bloqueado y no va el programa hacia adelante, la única solución es cambiar la intrucciones y hacer:

Servidor:

Coge el INPUT
Coge el OUTPUT

Cliente:

Coge el OUTPUT
Coge el INPUT

La verdad es que no se si es un problema de concepto mio, o es un problema que tiene Java, a ver que me podeís comentar.

Muchas Gracias!

Etiquetas: stream
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 16:48.