jueves, 29 de marzo de 2007

e3: tamaño incorrecto

> Al cifrar me salen ficheros demasiado grandes. He escrito esto: ..."
> int nDatos = entrada.read(datos);
> while (nDatos > 0) {
> String texto = codificador.codifica(datos);

pues muy mal: sólo puedes codificar "nDatos";
repasa los métodos de la clase base64.Codificador.

> Al descifrar me salen ficheros demasiado grandes. He escrito esto: ..."
> int nDatos = entrada.read(datos);
> while (nDatos > 0) {
> String criptograma = new String(datos);
> String mensaje = descifrador.descifra(criptograma);

pues muy mal: sólo puedes descifrar "nDatos";
repasa los constructores de la clase String.

miércoles, 28 de marzo de 2007

e3: ¿cómo funciona read()?

Con bytes.
Si tenemos un lector de bytes
InputStream in= new FileInputStream("fichero");

necesitamos un sitio donde leer bytes: un array de tamaño T
byte[] datos= new byte[T];

Cada vez que llamamos a "read()" le pasamos el sitio donde queremos cargar bytes
int n= in.read(datos)

"read()" hace 2 cosas
1. carga bytes en el array "datos" (hasta un máximo de T, si lo hay)
2. nos devuelve en "n" cuántos bytes ha logrado cargar

Por eso, si "n <= 0" es que no hay nada que cargar: se ha acabado el fichero.

Y si "n > 0", podemos usar "n" datos: entre las posiciones "0" y "n-1" del array.

"read()" nunca lee dos veces los mismos datos, sino que en cada llamada va
avanzando por el fichero y lee los datos que hay a continuación.
De esta forma, llamando a "read()" dentro de un bucle,
vamos obteniendo los bytes sucesivos que contiene el fichero.

Con caracteres.
Lo mismo, pero cambiando "InputStream" por "Reader"
y "byte[]" por "char[]".

martes, 27 de marzo de 2007

e3: exactamente ¿cuántos datos leo?

Si haces algo así

byte[] datos= new byte[1024];
int n= inputStream.read(datos);

n puede ser cualquier número entre -1 y 1024.

Si es <=0, es que no hay nada que leer:
lo has leido todo y puedes acabar.

Si n > 0 has leído n datos, que están en las primeras n posiciones del array.

Para codificarlo, no puedes hacer
String codificada= codificador(datos);
sino que tendrás que usar otro método de la clase que sólo codifique n bytes

http://www.lab.dit.upm.es/~lprg/curso/e3/doc/base64/Codificador.html

--------------------
Algo parecido ocurre al descifrar,
int n= reader.read(datos);

De los n caracteres válidos en datos, hay que hacer una String,
mira los constructores disponibles:

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html

e3: ¿qué eso de termina() del codificador?

Ocurre que para pasar a base64 se necesita un múltiplo entero de 3 bytes.
Si los datos que pasas a codificar no son un múltiplo entero de 3,
pues el decodificador sólo codifica los grupos de 3 que encuentra
y se guarda el resto para cuando le mandes codificar más
(empezará con los que tiene como restos de la última llamada).

Eso va muy bien mientras hay más bytes que leer,
pero cuando el fichero de entrada se acaba
hay que decirle al codificador que ya no guarde más,
sino que vacie los restos.

Para eso, al acabar, se llama a
String restos= codificador.termina();

... y esos restos hay que cifrarlos y escribirlos en la salida cifrada.

Aunque probablemente no lo necesites conocer en detalle,
si tienes curiosidad por eso del base64
puedes ilustrarte en la wikipedia:

http://en.wikipedia.org/wiki/Base64

para hacer el ejercicio basta con usar las clase del paquete base64.

lunes, 26 de marzo de 2007

e3: ¿dónde están los ficheros?

Todo se hace a partir del sitio donde hayas puesto en ejercicio,
el código java y los ficheros de prueba.

Saco una foto de mi ordenador:

http://jungla.dit.upm.es/~pepe/doc/lprg/e3_msdos.png

e3: ya lo he escrito todo pero ni funciona ni compila, ¿qué hago?

Salvo que tengas mucha experiencia, escribirlo todo y luego intentar compilar
puede ser bastante mala idea.

Lo ideal es escribir un poquito, poner trazas, compilar y ejecutar
(con trazas y, si ya es posible, con un caso de pruebas).

Cuando funcione un poquito, haces otro poquito y así, paso a paso,
acabarás mucho antes que con todo de golpe.

Bueno, nunca hay dos experiencias iguales; es un consejo.

domingo, 25 de marzo de 2007

e3: ¿cómo escribo caracteres en el fichero?

Esto está bien:

String cifrado= cifrador.cifra(...);
char[] caracteres= cifrado.toCharArray();
writer.write(caracteres);

Esto está también bien, y es más directo:

String cifrado= cifrador.cifra(...);
writer.write(cifrado);

e3: ¿por dónde empiezo?

Por el principio, por supuesto. Y vas añadiendo funciones poco a poco, compilando y comprobando que lo hecho funciona bien antes de pasar a lo siguiente. Para "ver" si va bien necesitarás trazas y usar los casos de prueba publicados.

1. Crea la clase cifrador.ui.CifradorFicheros
importando los cifradores y descifradores incrementales,
así como los codificadores y descodificadores base64

2. Crea un Logger con el nombre del enunciado
(puedes crear loggers tuyos con otros nombres)

3. Crea el método main
copiando el javadoc del enunciado

4. Captura los argumentos y escribe la traza que se pide

ya puedes empezar a compilar y ver si funciona ...

5. Usa el primer argumento para decidir si tienes que cifrar o que descifrar
y actua en consecuencia, siempre trazando para comprobar que vas bien

e3: sobre el nombre de los ficheros

Los nombres de los ficheros serán los que aparezcan al llamar al programa,
exactamente como se le pasan al llamar al programa.

Por ejemplo si le llamas como

$> java cifrador.ui.CifradorFicheros -c evalc cita.txt cita-cifrada

se utilizará la clave "evalc" para leer el fichero "cita.txt" y escribir el fichero "cita-cifrada".

Nosotros hemos puesto parejas de ficheros de prueba, por ejemplo

CancionDelPirata.txt y CancionDelPirata.vgn

Si los vas a usar como prueba, tienes que hacer algo así

...> java cifrador.ui.CifradorFicheros -c AEIOU CancionDelPirata.txt cifrado

...> java ComparaFicheros cifrado CancionDelPirata.vgn
cifrado y CancionDelPirata.vgn son idénticos

...> java cifrador.ui.CifradorFicheros -d AEIOU CancionDelPirata.vgn descifrado

...> java ComparaFicheros descifrado CancionDelPirata.txt
descifrado y CancionDelPirata.txt son idénticos

jueves, 22 de marzo de 2007

e3: java no se sabe ejecutar "if (args[0] == "-c") ..."

Normal,
para comparar String hay que usar equals().

Mira
http://jungla.dit.upm.es/~pepe/doc/fprg/vademecum.pdf
equals (método) public boolean equals(Object)
Igualdad (==)
String (clase) java.lang.String

e3: ¿puedo poner algunos métodos provados?

Sin duda: su puedes.

Aunque no es obligatorio, la verdad es que queda muy bien si pones
un método para cifrar y otro para descifrar,
así en el main, con un IF decides a cual llamar
y en cada método te centras en lo que tiene que hacer.

miércoles, 21 de marzo de 2007

e3: ¿se necesita un nuevo array en cada lectura?

No.
Lo normal es crear un array (de bytes o caracteres, según necesites)
antes del bucle de lectura.
Al principio el array está lleno de ceros.
Cada vez que lees se cargan nuevos valores en las primeras posiciones,
machacando los valores anteriores.

Ojo con lo que devuelven los métodos de lectura,
sólo son buenos los primeros valores,
los demás son restos de otra época.

e3: al cifrar, ¿necesito un char[]?

Es cierto que el cifrador devuelve una String,
puedes pasarla a un char[] para guardarla en el disco:

String criptograma= cifrador.cifra(...);
char[] chars= criptograma.toCharArray();
writer.write(chars);

o puedes hacerlo directamente

String criptograma= cifrador.cifra(...);
writer.write(criptograma);

viernes, 16 de marzo de 2007

e2: al descifrar me salen códigos negativos ¿qué pasa?

Es normal, y debes tenerlo en cuenta.

Si ctc es el código del texto cifrado (criptograma)
y ccl es el código de la clave,
debes hacer algo así al descifrar

while (ctc < ccl) ctc+= ALFABETO.length;
ctd= (ctc - ccl) % ALFABETO.length;

siendo ctd el código del texto descifrado.

jueves, 15 de marzo de 2007

e2:¿qué pasa si no entrego el viernes?

Bueno, el ejercicio es obligatorio y debes hacerlo antes de junio;
si no, no podremos aprobarte la asignatura.

Para los ejercicios no aceptados en la primera entrega,
habilitaremos fechas de repesca.

No obstante, la nota no será la misma si se entrega en la repesca.
Mira los criterios de evaluación.

¿qué pasa si mi código es como el de un compañero?

Sistemáticamente pasamos un detector de copias.
Si dos entregas son iguales, consideramos que ambos habeis copiado
y os suspendemos a los dos en junio.

Suena duro,
pero es que la evaluación es individual y no podemos hacer otra cosa.

miércoles, 14 de marzo de 2007

e2: es un ejercicio de arrays, ¿verdad?

Pues puedes hacerlo con arrays o no.

Si quieres hacerlo con arrays, pasarás de String a array usando "charAt()" o "toCharArray()"
y volverás de array a String usando "new String(array)".

Si no quieres usar arrays, puedes acceder a los String con "charAt()",
añadiendo cosas con "+".
Incluso puedes optimizar el código usando un "StringBuilder()".

¿Qué es un StringBuilder?
mira el vademecum
http://jungla.dit.upm.es/~pepe/doc/fprg/vademecum.pdf

e2: esto que he hecho, ¿está bien?

¿Pasa las pruebas que preparaste en el ejercicio e1?

sábado, 10 de marzo de 2007

e2: hasta que no funcione no pongo trazas con Logger

Tu estás tonto (por decirlo finamente).

Las trazas son para poner a punto el programa y localizar rápidamente los fallos.

Poner trazas sólo cuando funcione comprendo que es necesario para que te aprobemos
el ejercicio, pero realmente estás perdiendo tu tiempo.

Si te sobra el tiempo, sigue buscando errores a ciegas.
Pero si tienes cosas más interesantes que hacer en la vida,
pon trazas en los programas según escribes el código
y así lo pondrás a punto mucho más rápidamente.

Para que no interfiera con las trzas que te has pedido,
a tus trazas ponles otro nombre
MI_LOG= Logger.getLogger("cifrador.MiCifrador.mis_trazas");

Y NO LAS QUITES CUANDO LO ENTREGUES.

e2: hasta que no funcione no documento ...

Pues muy mal hecho.

Lo primero que hay que hacer es escribir lo que tiene que hacer un método.
No deberías poner ni una línea de código hantes de
tener perfectamente claro
* los argumentos que recibe,
* lo que significan,
* el resultado que debe devolver
* y las posibles excepciones

e2: ¿vale poner métodos privados?

Sí, por supuesto.

Es más, yo diría que necesitarás definir algunos métodos privados
para que el código quede legible.

No olvides documentar con javadoc los métodos privados.
/** ... */