Clase 24-05-24 - 1 - Contenido educativo
Ajuste de pantallaEl ajuste de pantalla se aprecia al ver el vídeo en pantalla completa. Elige la presentación que más te guste:
su capa más básica para acceder a ficheros
00:00:02
su capa más básica trabaja en dos modos
00:00:07
el modo carácter que es asumiendo que el fichero lo que tiene es texto
00:00:10
es decir, que esos bits que tiene
00:00:15
si los agrupamos de 8 en 8 tiene una correspondencia en la tabla ASCII
00:00:17
que representa un carácter
00:00:22
o el modo byte
00:00:23
o el modo byte
00:00:25
entonces en el modo byte
00:00:27
no hacemos ninguna
00:00:35
suposición sobre el contenido del archivo
00:00:36
asumimos que un archivo
00:00:39
es una lista de ceros y unos
00:00:40
y lo que codifique
00:00:43
pues vete a saber, dependerá de la aplicación
00:00:44
que lo haya generado, si lo ha generado el Word
00:00:47
pues codificará
00:00:49
la codificación
00:00:51
interna del Word, sea la que sea
00:00:53
si lo ha generado el Excel, pues la codificación interna
00:00:54
del Excel, un fichero al fin y al cabo
00:00:57
es eso, es una sucesión de bits
00:00:59
uno tras otro, entonces en algunos
00:01:00
casos
00:01:03
esos bits si los agrupamos de 8 en 8
00:01:03
hacemos la correspondencia con
00:01:07
la tabla ASTI, vemos
00:01:09
un texto con sentido
00:01:10
y eso es un fichero de texto
00:01:12
pero en muchísimos otros casos
00:01:15
esa ristra de bits
00:01:17
no se corresponde con caracteres
00:01:18
de la tabla ASTI, sino se corresponde
00:01:21
con lo que
00:01:23
la aplicación haya generado para
00:01:25
guardar su propia información
00:01:26
y toda esa rista de bits
00:01:28
para que sea interpretable
00:01:30
es esa misma aplicación
00:01:32
Word, Excel, la que sea esa misma
00:01:34
la que lo tiene que abrir, porque si no
00:01:36
es imposible entender de ahí nada
00:01:38
entonces
00:01:40
Java ofrece unas clases
00:01:42
para, asumiendo que los bits
00:01:44
vienen de donde vengan, simplemente
00:01:46
dedicarse a moverlos
00:01:48
moverlos a
00:01:50
memoria principal o volverlos a llevar
00:01:52
al fichero, pero no valen para nada más
00:01:54
porque no puede extraer ninguna información sobre esos bits
00:01:56
no puede extraer ninguna, no valen para nada más
00:01:58
entonces las voy a mencionar solo para que las conozcamos
00:02:00
porque son las básicas sobre las que se monta todo
00:02:03
y esas clases básicas sirven simplemente
00:02:06
para mover bits de 8 en 8
00:02:09
de nuestro fichero a variables de Java
00:02:12
y para volverlas a llevar de variables de Java aquí
00:02:15
y solamente valen para eso
00:02:18
luego ya esos bits que están ahí movidos ya en variables de Java
00:02:20
si esa aplicación Java
00:02:23
tiene información sobre lo que le significan
00:02:26
son de Word, son de no sé qué
00:02:28
puede plantearse hacer cosas con ellos
00:02:30
si tiene esa información añadida sobre lo que significan
00:02:31
pero si no, son 8 bits que no significan
00:02:33
nada para ella
00:02:36
para la aplicación Java, no significan
00:02:37
porque tienen una codificación que depende
00:02:40
de la aplicación
00:02:42
¿vale? entonces
00:02:43
repito, voy a mencionarlas porque son
00:02:45
las básicas o las que se montan todas las
00:02:48
demás, pero
00:02:50
su uso es simplemente ese
00:02:51
coger de un fichero, que son
00:02:53
un montón de bits, mover los bytes
00:02:55
de uno en uno a la aplicación
00:02:58
a variable y ya está
00:02:59
bueno, pues esas clases, las que trabajan
00:03:01
en modo byte
00:03:03
serían estas
00:03:05
file input
00:03:07
stream, para leer
00:03:10
es decir, cuando digo leer
00:03:18
digo mover del fichero
00:03:20
a variables de java
00:03:21
y file output stream para escribir
00:03:23
vale, pues entonces repito
00:03:26
vamos a ver un ejemplo mínimo de cómo
00:03:37
funcionan, pero entendiendo que
00:03:39
su uso
00:03:41
es muy muy muy limitado, porque lo único que hacen
00:03:42
es mover, entonces a lo mejor ¿para qué nos pueden servir?
00:03:45
pues nos pueden servir para copiar
00:03:48
un fichero en otro, por ejemplo, para eso sí
00:03:49
porque cuando yo quiero copiar un fichero en otro
00:03:51
desde una aplicación Java
00:03:53
lo que contiene
00:03:55
la información, lo que significa, el significado
00:03:57
me da igual, lo único que quiero
00:03:59
es llevar estos bits aquí
00:04:01
lo único que quiero es eso, el significado me da igual
00:04:02
pues si el significado me da igual
00:04:05
con estas clases tengo suficiente
00:04:07
porque lo que haré será
00:04:09
llevar a la aplicación java
00:04:10
y luego de la aplicación java llevar al otro
00:04:13
¿vale? entonces
00:04:14
en aplicaciones java
00:04:16
que necesiten trasladar esos bits
00:04:18
o hacer cosas con esos bits
00:04:21
pero sin importarles
00:04:23
en absoluto lo que representan
00:04:25
pues estas clases pueden ser suficientes
00:04:27
¿vale? vamos a hacer ese ejemplo
00:04:29
sin más, un ejemplito de una aplicación
00:04:31
java para copiar un fichero
00:04:33
en otro, por ejemplo, con otro
00:04:35
nombre y ya está
00:04:37
y luego ya pasamos a clases
00:04:38
que ya están montadas sobre
00:04:41
estas que hacen cosas un poquito más
00:04:43
sofisticadas, ¿vale? pero están
00:04:45
montadas sobre estas que son la base
00:04:47
las de mover bits de un lado a otro
00:04:49
venga, pues vamos a
00:04:51
hacernos aquí en el proyecto
00:04:53
ejemplo que estábamos
00:04:55
otro paquete
00:04:56
que lo vamos a llamar
00:04:58
modo byte
00:05:02
para que
00:05:03
sepamos que ahí está el ejemplito
00:05:04
para hacer esta aplicación Java
00:05:10
que usa estas clases que hemos dicho
00:05:11
para copiar un fichero en otro
00:05:13
pues venga
00:05:14
nos hacemos una clase cualquiera
00:05:16
que va a tener ya el main
00:05:19
copiar ficheros
00:05:20
vale
00:05:26
venga pues en esta clase vamos a hacer un método
00:05:27
que va a servir
00:05:34
para
00:05:36
he dado un nombre de fichero
00:05:40
origen y un nombre de fichero destino
00:05:42
copiar el fichero origen en el fichero destino
00:05:44
como si hiciéramos un move del sistema operativo
00:05:47
desde la línea de comandos
00:05:49
pues venga
00:05:52
vale, pues este método vamos a hacer
00:05:54
le vamos a pasar los nombres
00:06:01
directamente es como si simularamos el
00:06:02
el copy
00:06:05
del move o como lo queréis llamar
00:06:06
del sistema operativo
00:06:09
que recibe le ponemos dos nombres
00:06:10
le ponemos ahí dos cadenas
00:06:11
pues entonces
00:06:13
vale
00:06:15
Fichero origen
00:06:19
Y el otro
00:06:23
Fichero destino
00:06:26
Ala
00:06:32
Bueno, pues entonces
00:06:35
Aquí uno ve este método y dice
00:06:37
¿Qué tengo que hacer con esto?
00:06:39
Este fichero tiene unos bits
00:06:41
Y este tiene otros
00:06:42
El objetivo es que estos bits se muevan aquí
00:06:44
¿Tengo que interpretar algo sobre su contenido?
00:06:47
No tengo que interpretar nada
00:06:51
Solo tengo que moverlos de un sitio a otro
00:06:52
No tengo que interpretar nada
00:06:53
pues entonces estas clases
00:06:55
input, file, input, string, file, output
00:06:57
nos valen, porque estas clases valen
00:06:59
para mover, nada más
00:07:01
para trasladar, pues estas me valen
00:07:03
que son las más básicas, las más sencillas
00:07:05
las que menos carga computacional tienen
00:07:07
vale, pues entonces
00:07:09
una aplicación java
00:07:11
para acceder a ficheros
00:07:12
ya sabemos que puede hacer
00:07:15
dos cosas, o leer
00:07:17
y leer es
00:07:19
coger del fichero y llevarlo a variables internas
00:07:20
para con esa
00:07:23
una vez que ya están variables internas
00:07:25
hacer con eso lo que sea
00:07:27
o escribir que es lo que tienen variables internas
00:07:27
llevarlo a un fichero
00:07:31
esas son las dos cosas
00:07:32
que se pueden hacer con ficheros
00:07:35
desde una aplicación Java
00:07:36
coger su información
00:07:38
y traerla a variables
00:07:40
de la aplicación
00:07:43
o contenido que está en variables
00:07:44
moverlo a ficheros
00:07:47
esas son las dos cosas que se puede hacer
00:07:48
y luego ya con esa información
00:07:50
que está en variables uno ya procesa
00:07:52
hace todo lo que necesite hacer
00:07:54
porque
00:07:56
de nuevo repito, una aplicación Java
00:07:58
cuando opera con datos
00:08:00
esos datos tienen que estar en variables
00:08:02
ahí sí que no hay tutía, tienen que estar en variables
00:08:04
me da igual qué tipo de variables
00:08:06
primitivas, colecciones, objetos, pero una aplicación
00:08:08
Java solo puede trabajar con los datos
00:08:10
que están en sus variables
00:08:12
¿de dónde han llegado
00:08:13
esos datos? ¿que me los han metido en la
00:08:16
consola? ¿que los he leído de un fichero?
00:08:18
bueno, pues ya veremos, depende
00:08:20
pero una aplicación solo puede operar
00:08:22
con lo que tienen sus variables
00:08:24
y como cuando la aplicación termina
00:08:25
lo que está en las variables
00:08:28
se borra porque las variables
00:08:30
desaparecen, pues por eso
00:08:32
uno se tiene que preocupar si quiere
00:08:34
que esa información se conserve de llevarla
00:08:36
a un fichero antes de que la aplicación
00:08:38
termine o lo que sea
00:08:40
bueno, pues entonces aquí nuestra operación
00:08:41
es estos bits que están en este fichero
00:08:44
tienen que ir a estos bits que están en este
00:08:46
como lo único que puede hacer Java es
00:08:47
llevar de
00:08:50
fichero a variable
00:08:52
o de variables a fichero, pues tendremos que hacer
00:08:54
esos dos pasos, primero llevamos
00:08:56
de este fichero a variables
00:08:59
y luego llevamos de variables
00:09:01
a este fichero, esos dos pasos hay que hacerlos
00:09:02
porque no se puede llevar de un fichero
00:09:04
a otro directamente, siempre hay que pasar
00:09:07
por RAM, vale
00:09:08
el disco duro no se puede
00:09:10
comunicar entre sí directamente, de un sector
00:09:12
a otro, es imposible, siempre tiene que viajar
00:09:14
a la memoria RAM y salir otra vez
00:09:16
vale, pues aquí
00:09:19
igual, yo tengo dos ficheros
00:09:21
uno tiene que viajar a las variables de mi aplicación
00:09:23
a la RAM y de ahí irse a el otro fichero
00:09:26
vale, pues entonces vamos a hacer primero la operación de lectura
00:09:30
la de lectura es, voy a leer de uno y luego voy a escribir en otro
00:09:33
bueno, pues leer bytes de un fichero, el file input string
00:09:38
pues nada, lo instanciamos aquí, y como se instancia
00:09:42
este objeto file input string, pues como el file reader
00:09:50
le damos
00:09:53
o bien el nombre
00:09:55
del fichero directamente
00:09:58
o el objeto file asociado
00:09:59
el constructor me permite las dos variantes
00:10:01
igual que file reader
00:10:03
como tenemos el nombre
00:10:04
vamos a usar el constructor
00:10:06
que recibe el nombre
00:10:08
el string con la cadena de texto que es el nombre
00:10:10
vale, pues ya tenemos un
00:10:13
flujo conectado a un fichero
00:10:19
con este nombre, hay preparado
00:10:21
para hacer operaciones de lectura
00:10:23
es decir, para hacer operaciones
00:10:24
de coger del fichero y llevar
00:10:27
a la memoria RAM
00:10:29
a variables
00:10:31
esto habrá que importarlo, claro, del paquete
00:10:31
java.io
00:10:35
y de nuevo, esta operación
00:10:35
puede lanzar una excepción
00:10:39
file not found exception
00:10:40
y te dice, tienes que capturarla
00:10:42
o avisar, para quien use este método
00:10:45
pues por no complicar el código
00:10:47
la propagamos
00:10:49
throws, ala, ya está
00:10:50
y ahora toca leer
00:10:53
bueno, pues esto es el mismo bucle de lectura
00:10:54
el mismo que con el FileReader
00:10:57
cada lectura, este tiene un método read
00:10:59
igual que tenía el FileReader
00:11:03
este método
00:11:05
este método que te hace, te lee un byte
00:11:07
silencio
00:11:09
con leerte un byte
00:11:11
me refiero, coge un byte del fichero
00:11:13
y te lo lleva
00:11:15
a una variable
00:11:17
del programa
00:11:18
¿a qué tipo de variable? a una variable de tipo byte
00:11:20
podría ser porque cabe
00:11:23
en una variable de tipo byte, pero no
00:11:25
te lo lleva a una variable
00:11:27
de tipo int
00:11:29
ahí te lo lleva
00:11:30
entonces, esto que hemos hecho aquí
00:11:32
bueno, aparte de que puede hacer una excepción
00:11:35
y o exception que vamos a propagar
00:11:37
esta sentencia de aquí
00:11:39
te lee un único byte
00:11:42
del fichero, lo coloca
00:11:45
en el byte menos
00:11:47
significativo de la variable n
00:11:49
que ya sabéis que tiene 4
00:11:50
en el byte menos significativo
00:11:52
lo coloca, el resto lo deja a ceros
00:11:55
y el posicionador interno
00:11:56
del fichero lo avanza para que
00:11:59
en la siguiente lectura, en el siguiente read
00:12:00
leamos el siguiente, exactamente igual que con
00:12:02
el file reader
00:12:04
en realidad
00:12:07
la única diferencia es que con el file reader
00:12:07
si luego hacíamos el casting a char
00:12:10
pues nos daba un carácter, aquí no
00:12:12
nos da nada, porque lo mueve tal cual
00:12:14
es que no hace ninguna
00:12:17
los bits tal cual son, nos lleva a n
00:12:18
Vale, pues entonces
00:12:21
¿Y qué queremos hacer con cada uno de ellos?
00:12:24
Llevarlos al otro
00:12:27
Mismo bucle de lectura que en el file reader
00:12:28
Tendremos que hacer tantos read de estos
00:12:32
Tantos read como bytes haya
00:12:35
Esto habrá que meterlo en un while, ¿verdad?
00:12:37
Entonces el bucle de lectura se queda igual que el file reader
00:12:41
Mientras
00:12:43
Yo aquí declararía mi variable n
00:12:46
Y mientras n, siendo n el resultado de hacer una lectura, sea diferente de menos 1, porque tenemos la misma forma de avisar que con el file reader.
00:12:49
La sentencia esta read, coge un byte y lo lleva a n, a la parte menos significativa, el resto lo pone todo a ceros.
00:13:16
vale, que ocurre
00:13:24
si este react intenta leer
00:13:27
la marca fin de archivo
00:13:29
porque ya acabamos, intenta leer la marca
00:13:31
fin de archivo
00:13:32
en este numerito n
00:13:34
lo que coloca es el número entero
00:13:36
menos uno, entonces como el número entero
00:13:38
es menos uno, es negativo
00:13:41
y por tanto su bit de signo es uno
00:13:42
luego no, es la forma
00:13:44
de ver que ese no es un byte
00:13:47
del fichero, porque si fuera un byte del fichero
00:13:49
este numerito n tendría todos ceros aquí
00:13:50
con lo cual es imposible que sea menos uno
00:13:53
porque su bit de signo es cero, es positivo
00:13:55
entonces si esto hubiera
00:13:57
hecho una lectura
00:13:59
válida, una lectura válida
00:14:01
jamás podría ser menos uno
00:14:03
jamás podría ser menos uno, podría ser lo que fuera
00:14:05
pero no menos uno porque el bit de signo sería
00:14:07
cero, luego sería un positivo
00:14:09
si me devuelve menos uno
00:14:11
es porque lo que ha leído
00:14:14
es la marca fin de archivo, entonces lo ha colocado
00:14:16
todo a unos
00:14:17
y entonces es mi manera de ver
00:14:18
que, ah, vale, vale
00:14:21
no has conseguido mover un byte
00:14:22
no lo has conseguido, pues si hubieras conseguido
00:14:25
n tendría un número positivo
00:14:27
el que fuera, pero positivo
00:14:29
no lo has conseguido, me estás avisando
00:14:31
poniendo menos uno en ese n
00:14:33
pues ya está, esta es la misma
00:14:35
condición de fin de archivo en el file real
00:14:37
pues mientras n, siendo n
00:14:39
el intento de leer
00:14:41
el byte, no me haya
00:14:43
devuelto este resultado
00:14:45
mientras no me lo haya devuelto, yo ya con n
00:14:47
hago ahí lo que quiera, n es un byte
00:14:49
que tiene bits, que a saberlo decodifica eso
00:14:51
ni idea, un char no
00:14:53
no tiene por qué, ni idea
00:14:55
vale, en este ejemplo en concreto, ¿qué queremos hacer
00:14:57
con sn? queremos mandarlo al otro
00:14:59
archivo, y así, leemos byte
00:15:01
escribimos, leemos byte, escribimos, leemos byte
00:15:03
escribimos, el otro archivo está
00:15:06
sin abrir, pues vamos a
00:15:07
abrirlo, este, como este caso es
00:15:09
para escribir
00:15:11
pues vamos a
00:15:12
abrirlo con file output
00:15:15
stream
00:15:17
que es para escribir bytes
00:15:20
de nuevo el constructor
00:15:22
o bien se le pasa
00:15:30
la cadena de texto que tiene el nombre
00:15:32
o el objeto file asociado
00:15:34
da igual, admite ambas opciones
00:15:36
como tenemos la cadena de texto
00:15:38
en lugar de hacer new file esa cadena
00:15:39
pues le pasamos el nombrecito
00:15:41
y ya está, fichero
00:15:44
destino
00:15:47
y este admite un segundo
00:15:49
parámetro que tiene la misma
00:15:55
utilidad que en el file writer
00:15:57
que es, cuando yo abro este fichero
00:15:59
puede ocurrir dos cosas
00:16:01
que este ya exista
00:16:03
de antes o que no exista
00:16:05
si no existe de antes
00:16:07
se crea nuevo y limpio
00:16:09
pero y si existe de antes
00:16:10
¿qué hace? pues si existe de antes
00:16:13
lo abro para escribir pero tengo dos opciones
00:16:15
me posiciono al final para añadir
00:16:17
o me posiciono al principio
00:16:20
y todo lo que hay después
00:16:22
lo tiro a la basura
00:16:23
¿cuál de las dos opciones escoge?
00:16:24
depende de si yo aquí pongo true o false
00:16:27
si pongo true
00:16:29
se posiciona al final
00:16:31
para añadir a continuación
00:16:33
de lo que ya hubiera, exactamente igual que
00:16:35
en el file writer, igual, si pongo
00:16:37
false, no añade, se posiciona
00:16:39
al principio, elimina lo demás
00:16:41
si no ponemos nada
00:16:42
la opción por defecto es como haber puesto false
00:16:44
todo esto es igual que el file writer
00:16:46
en nuestro caso, vamos a copiar
00:16:48
este en este otro
00:16:51
si el fichero existe, pues lo vamos a sobrescribir
00:16:52
podríamos, si queremos hacer
00:16:55
este método más bonito, por ejemplo
00:16:59
podríamos hacer aquí, vamos a ver si existe
00:17:01
y si existe avisamos
00:17:03
desea sobre escribir
00:17:05
¿cómo podríamos ver si este archivo existe?
00:17:06
pues para esto tenemos la clase file
00:17:10
que me permite obtener información sobre el archivo
00:17:11
si existe, si es de lectura, escritura
00:17:13
pues podríamos instanciar un objeto
00:17:15
file asociado
00:17:17
a ese archivo
00:17:19
a este
00:17:22
fichero destino
00:17:26
y ahora podríamos hacer
00:17:29
Si el fichero existe, le preguntamos
00:17:33
¿Desea sobrescribir sí o no?
00:17:37
Y si te dice que no desea sobrescribir, retún
00:17:38
Ya está, que no haga nada
00:17:41
Podemos hacer eso, ¿no?
00:17:42
Si f.existe
00:17:45
Si el fichero existe, este fichero
00:17:49
Pues le podríamos preguntar ahora ya sí
00:17:52
El fichero existe
00:17:55
¿Desea sobrescribir?
00:18:05
leemos
00:18:15
su respuesta
00:18:16
si no
00:18:18
para lo cual pues hay que leer del teclado
00:18:19
con escáner o con lo que
00:18:28
os dé la gana
00:18:30
aquí ya la tengo ahí
00:18:31
vale
00:18:42
yo leo con
00:18:42
esta clase
00:18:44
y yo haría ya directamente
00:18:46
si teclado.leercadena
00:18:52
es
00:18:54
igual a no, no desea sobrescribir
00:18:57
es igual
00:19:00
a n
00:19:03
pues entonces, como me ha dicho
00:19:04
que no, ya no tengo más que
00:19:12
hacer el método que termine
00:19:14
por ejemplo, pues que termine
00:19:15
entonces aquí ya le puedo poner directamente
00:19:17
eh
00:19:20
return
00:19:21
y listo, vale
00:19:23
entonces si el fichero existe
00:19:25
me avisa y me dice
00:19:27
¿quiere sobreescribir? le digo que no
00:19:29
vale, pues termina
00:19:31
¿que no le he dicho que no?
00:19:32
No entraría aquí, el método sigue y ahora ya hace todo esto.
00:19:35
De hecho, esto lo voy a poner para que lo haga aquí solo si lo necesita.
00:19:38
Bueno, pues nada.
00:19:49
Hemos dicho que o bien no existe, con lo cual no ha entrado en este if,
00:19:52
o bien no existe, o bien existía, pero ha dicho que sobrescribe.
00:19:57
En cualquiera de esas dos cosas, si no existe o si existiendo quiere sobrescribir,
00:20:00
en cualquiera de ellas hemos llegado a este punto.
00:20:04
hemos llegado a ese punto, vale, pues abrimos esto para leer, que es lo que estábamos, abrimos esto para escribir, vale, no le ponemos que añada, porque nos ha dicho que sobrescribe, pues así se queda, importamos de aquí, y nos dice la excepción, espérate, algo, he escrito algo mal, porque, ah, no, no, vale, vale, y ahora ya,
00:20:07
voy leyendo del primero
00:20:39
con cada byte leído, ¿qué quiero hacer?
00:20:41
llevarlo al otro, y se acabó
00:20:43
y para eso tendré
00:20:45
un método GRUITE al que le paso
00:20:46
ese byte
00:20:49
y ya está
00:20:51
¿y el GRUITE qué hace?
00:20:52
el GRUITE coge el byte
00:20:55
menos significativo de este
00:20:57
el menos significativo
00:20:59
porque en ese es en el que está la información
00:21:01
el resto están solo
00:21:02
para habilitar esa posibilidad de poner el menos uno
00:21:04
solo están para eso
00:21:07
pero no tienen información
00:21:08
la única información está en el byte
00:21:10
menos significativo de n
00:21:13
vale, pues este lo que hace es eso
00:21:14
coge el byte
00:21:18
menos significativo de n
00:21:20
que es donde se guardó lo que leyó
00:21:22
y va al otro
00:21:24
y se acabó, cuando este bucle ha terminado
00:21:24
pues ya podemos cerrar los dos
00:21:28
y listo
00:21:30
bueno, pues con este
00:21:37
ejemplito sencillo en el cual
00:21:38
lo único que necesitamos es coger los bytes
00:21:40
Llevarlos a sitios, pero lo que codifiquen nos da igual
00:21:42
Pues con estas dos clases que son de muy bajo nivel
00:21:45
Y por tanto muy eficientes computacionalmente
00:21:49
Pues nos vale
00:21:51
Si vamos a probarlo ahora
00:21:52
Desde aquí
00:21:59
Fichero origen
00:22:02
Y aquí
00:22:06
Fichero origen
00:22:14
Le voy a pedir el destino
00:22:20
Luego llamo al método
00:22:22
Fichero destino
00:22:23
Y ahora voy a llamar al método
00:22:30
Copiar fichero
00:22:33
Este que le he dicho
00:22:34
Copialo aquí
00:22:39
Y vamos a ver si funciona y lo copia
00:22:40
Como lanza excepción, pues me dice
00:22:44
Si tienes que hacer algo, pues throws
00:22:46
El throws se va aquí al main
00:22:48
Y ya está
00:22:49
Vale, entonces estoy en este fichero
00:22:51
Uy, en este proyecto
00:22:55
Vamos a probar
00:22:57
Este de aquí, destino
00:22:58
Vamos a copiarlo en destino2
00:23:02
Pues venga, ejecutamos esto
00:23:04
Fichero origen, este
00:23:10
Copialo en destino 2
00:23:15
No dice nada, suponemos que lo habrá copiado
00:23:18
Vamos a actualizar
00:23:22
Refresh ahí
00:23:25
Y destino 2 está aquí, que efectivamente tiene la misma información
00:23:29
Si dijéramos que copie destino en intercala
00:23:34
Que ya existe, es cuando me dirá lo de
00:23:37
¿Quieres sobreescribir patatín patatán?
00:23:40
vamos a probarlo
00:23:42
queremos copiar destino en
00:23:44
le voy a volver a decir destino2
00:23:47
que ya existe
00:23:49
¿desea sobreescribirlo? pues si le digo que no
00:23:49
pues ya está, ha terminado y no lo ha sobreescrito
00:23:54
y si le digo que sí, pues lo habría sobreescrito
00:23:56
aunque en este caso tendrían lo mismo ya
00:23:58
pero bueno, pues nada
00:24:00
queda ahí ese ejemplo
00:24:04
para ilustrar estas dos clases
00:24:05
que son las más básicas
00:24:08
de ese paquete
00:24:10
que mueven bytes
00:24:12
con este read que hemos visto y con el write
00:24:13
luego tiene nombre más métodos para hacer más cosillas
00:24:16
y eso, pero bueno
00:24:18
bueno, pues entonces
00:24:19
quedémonos por ahora con estas cinco clases
00:24:26
la clase file
00:24:28
reader, writer, input string, output string
00:24:30
con los ejemplos de uso que hemos visto
00:24:32
para que sirven, como las podemos
00:24:34
usar para algunas cosas básicas
00:24:36
y ahora ya vamos a saltar
00:24:38
a otras clases que nos pueden ser más útiles
00:24:40
bueno, pues estas otras
00:24:43
clases que vamos a ver tienen que ver con
00:24:47
esto de aquí, serialización
00:24:49
de objetos
00:24:52
tiene que ver
00:24:54
con este concepto
00:24:56
vale, pues nosotros en nuestra aplicación
00:25:01
en nuestras aplicaciones normalmente
00:25:03
las variables pueden estar
00:25:05
en variables primitivas, en numeritos enteros
00:25:07
en char, en string
00:25:10
pero muchísimas veces están
00:25:11
la mayoría de veces están en objetos
00:25:13
objeto alumno, objeto cliente
00:25:14
en nuestras aplicaciones
00:25:17
tienen de repente un montón de objetos alumno
00:25:18
y la aplicación se cierra
00:25:21
o se tiene que reiniciar
00:25:24
y todos los alumnos que se han dado de alta
00:25:25
se van a perder para que luego cuando la aplicación termine
00:25:27
tenga yo que meterlas de nuevo
00:25:30
hombre pues no, lo ideal es que todo eso
00:25:31
que tenemos en nuestras colecciones
00:25:34
en nuestros maps, en todo eso
00:25:36
pueda ir fácilmente a algún sitio
00:25:37
para que cuando la aplicación
00:25:40
se arranca o se reinicia pues automáticamente
00:25:42
vuelva otra vez
00:25:44
es el funcionamiento ideal, que no tengamos
00:25:45
que cada vez que arranca una aplicación meterle
00:25:48
todos los datos. Si los datos
00:25:50
son 30.000 usuarios, ¿los tenemos que meter
00:25:52
cada vez? Pues no.
00:25:54
Entonces, todo ese conjunto
00:25:56
de datos que está en colecciones
00:25:58
de objetos enormes, todo ese conjunto
00:26:00
de datos, su sitio
00:26:02
natural de alojarse, obviamente
00:26:04
es una base de datos.
00:26:05
Porque en una base de datos, además,
00:26:08
podemos guardar algo tan importante
00:26:10
como la estructura. Es decir,
00:26:12
no solo el contenido,
00:26:14
sino también una información
00:26:16
sobre el contenido, la estructura. Es decir,
00:26:18
tablas, yo tengo un alumno
00:26:20
el alumno tiene NIF, nombre y nota
00:26:22
pues hombre, ¿dónde va a estar
00:26:23
mejor guardado que en una tabla
00:26:26
que tiene también tres campos?
00:26:28
NIF, nombre y nota, estupendo
00:26:30
la misma estructura que tengo en la clase
00:26:31
la misma la tengo en una tabla
00:26:34
lo que está en las tres propiedades
00:26:35
está en tres campos, o sea, el sitio natural
00:26:37
para guardar objetos son las tablas
00:26:39
de las bases de datos
00:26:42
porque la estructura de propiedades es la estructura
00:26:42
de campos, es lo mismo
00:26:46
pero ahora aquí nos vamos a ver
00:26:47
como guardar los objetos
00:26:50
en bases de datos
00:26:53
eso se englobaría todo bajo un único nombre
00:26:56
que es el nombre de persistencia
00:26:59
persistencia en el contexto nuestro de desarrollo
00:27:01
tiene un único significado
00:27:03
que es que los datos de mi aplicación
00:27:06
estén permanentemente conectados a un soporte permanente
00:27:08
de forma transparente para mí
00:27:12
yo trabajo con los objetos
00:27:14
y eso está ahí permanentemente conectado a una base de datos
00:27:17
y así me tengo que despreocupar, desalvar, recuperar, etc
00:27:19
eso es lo que se llama persistencia
00:27:22
y todo eso exige unos frengos, unas clases
00:27:24
que se encarguen de hacer todo eso
00:27:28
todo eso es un módulo del año que viene
00:27:30
nosotros ahora lo que vamos a hacer es
00:27:32
hombre, para mí es algo, no quiero nada tan sofisticado
00:27:35
yo tengo una aplicación con 30 alumnos
00:27:39
cuando me acuesto por la noche yo quiero dejar el ordenador apagado
00:27:41
y cuando lo arranco por la mañana quiero que mis 30 alumnos
00:27:45
o mis 30 clientes sigan ahí en la aplicación
00:27:48
para seguir operando con ellos, quiero eso
00:27:51
simplemente, bueno pues
00:27:53
en situaciones así, ni siquiera tenemos
00:27:55
por qué habilitar un sistema gestor de base
00:27:57
de datos y poner ahí la base de datos, tampoco
00:27:59
hace falta, yo en
00:28:01
un fichero, me llevo mis
00:28:03
objetos y luego ahí los recupero
00:28:05
pero como me los llevo, no son
00:28:07
texto, son propiedades de un
00:28:09
objeto, es algo más raro, no me los puedo llevar con
00:28:11
un file writer, un file writer solo admite caracteres
00:28:13
un objeto no es eso, no es una sucesión
00:28:15
de caracteres, ¿cómo me los llevo?
00:28:17
Bueno, pues para eso se habilitan
00:28:19
unas clases muy sencillas de usar
00:28:21
que hacen esto
00:28:23
que decimos de llevar todo ese mogollón
00:28:25
que hay dentro de un objeto, que hay de todo
00:28:27
un nombre, un nif, todo ese mogollón
00:28:29
llevarlo a un archivo
00:28:31
y se le llama serializar
00:28:32
porque todo ese mogollón de propiedades
00:28:34
nif, nombre, nota, patatín
00:28:37
como que se las pone en filitas
00:28:39
se hace ahí una filita de bits
00:28:41
y eso se le llama serializar
00:28:43
lo convierto yo en una filita de bits
00:28:45
y esa filita de bits va al fichero
00:28:47
ese fichero cuando se abra
00:28:48
no es que no se pueda abrir, ahí no se entiende nada
00:28:51
porque esos son unos bits
00:28:54
que serializan de una manera interna
00:28:55
todo eso que está ahí, es que ahí es imposible abrirlo
00:28:57
pero claro, para eso están
00:28:59
las clases que deserializan
00:29:01
yo ahora cojo ese fichero
00:29:04
y cojo esa filita de bits
00:29:05
y me la llevo a la aplicación Java
00:29:08
la aplicación Java ya sí que lo puede entender
00:29:09
¿vale? entonces la serialización
00:29:11
lleva un fichero, ese fichero ya no se entiende ni papa
00:29:13
y nadie lo podrá abrir, pero luego si
00:29:15
desde otra aplicación hago la deserialización
00:29:17
vuelve otra vez
00:29:20
al objeto, y ese objeto
00:29:21
yo puedo trabajar con él
00:29:23
bueno, pues esas clases
00:29:24
de serialización de objetos serían
00:29:28
para serializar
00:29:29
hacia el fichero, es decir
00:29:32
llevar de objetos a fichero
00:29:33
serían object
00:29:35
output stream
00:29:37
esto es lo que sería
00:29:40
para escribir, ¿verdad?
00:29:45
para escribir al archivo y para leer sería esta vale esto sería para serializar y esto para
00:29:47
de serializar si es que ese verbo existiera que no existe bueno pues vamos a ver cómo
00:30:10
podemos usarlas en una aplicación por ahí vale pues venga vamos a hacernos una aplicación
00:30:24
vale, vamos a ver
00:30:34
si pudiéramos coger aquí
00:30:42
una que tuviera entidades
00:30:44
main model, tiene alumno
00:30:48
y luego tiene aquí unas operaciones
00:30:50
que son
00:30:52
insertar, mostrar datos
00:30:53
de un alumno
00:30:56
alumno tiene
00:30:57
matrícula, lista de asignaturas
00:30:59
vale
00:31:04
pues vamos a echarle un vistazo a esta aplicación
00:31:06
de ejemplo alumnos que tenemos aquí
00:31:07
que es una con las que
00:31:09
hemos trabajado en su momento para ver colecciones
00:31:11
vale, esta aplicación
00:31:14
que tenía, tiene
00:31:16
la única entidad con la que trabajaba
00:31:17
el alumno
00:31:19
vale, pues el alumno
00:31:21
se caracterizaba por su número de matrícula
00:31:25
su nombre, su edad
00:31:27
y un conjunto, una lista de asignaturas
00:31:28
de las que está matriculado, se supone
00:31:31
solamente el nombre en string
00:31:33
solamente el nombre
00:31:35
por eso se caracteriza el alumno
00:31:36
vale, aquí tenía sus guides, sus sets, etc
00:31:39
Y luego esta aplicación tiene unas funcionalidades, unas cosas que se puede hacer con esos alumnos que teníamos recogidas en esta clase de operaciones. Teníamos recogidas unas funcionalidades. Este proyecto está en la aula virtual, imagino.
00:31:41
vale
00:32:00
teníamos recogidas unas funcionalidades que eran
00:32:02
los datos
00:32:04
estaban en una lista de alumnos
00:32:06
aquí estaban los datos
00:32:08
ahí están los datos
00:32:09
y ahora, ¿qué podíamos hacer con esos datos?
00:32:11
que estaban en esa lista
00:32:15
luego cuando la aplicación arranca
00:32:16
eso está limpio
00:32:18
cuando la aplicación arranca ahí no hay ningún alumno
00:32:20
eso está limpio
00:32:23
vale, pues ¿qué hacíamos aquí con esta
00:32:24
con estos alumnos?
00:32:27
Podíamos insertar un alumno. Vale, pues insertamos el alumno y ya está. Mostrar datos de un alumno dado su número de matrícula. Pues mostrábamos los datos, patatín. ¿Qué más cosas hacíamos? Matricular a un alumno de una asignatura. Pues esto hacíamos.
00:32:29
¿qué más hacíamos? desmatricular a un alumno
00:32:51
de una asignatura
00:32:54
le quitábamos el string
00:32:55
¿vale?
00:32:58
eliminar a un alumno
00:33:00
pues lo eliminábamos con el remove
00:33:01
¿vale? alumno que tenía
00:33:04
más asignaturas
00:33:06
pues nada, aquí hacíamos el máximo
00:33:07
para ver que alumno tenía más asignaturas
00:33:10
al alumno mayor, pues lo mismo
00:33:12
el número de alumnos
00:33:14
matriculados
00:33:16
pues
00:33:17
matriculados en una asignatura
00:33:19
en una, en esta
00:33:22
y luego a ver
00:33:24
si existe matrícula
00:33:26
este
00:33:28
si esta matrícula estaba
00:33:28
en el
00:33:32
en la lista
00:33:32
¿vale? por eso hacíamos
00:33:34
retune contains, bueno
00:33:38
pues este era un proyecto que usamos
00:33:39
en su momento para
00:33:41
practicar con listas y ya está
00:33:43
hacer remove, contains y poco más
00:33:46
pero claro, en este momento dijimos
00:33:48
a ver, los datos
00:33:50
de la aplicación
00:33:52
tienen que estar en memoria principal
00:33:53
porque no los podemos tener en ningún soporte
00:33:56
permanente porque no sabemos
00:33:58
cuando la aplicación arrancaba, esta lista
00:33:59
estaba vacía, y luego ya según
00:34:02
la aplicación iba llamando a insertar alumno
00:34:04
pues ya estaban apareciendo alumnos
00:34:06
y luego ya podíamos eliminarlos
00:34:08
de todo, cuando la aplicación
00:34:10
se cierra, pues no hay
00:34:12
ningún alumno, o sea, los alumnos
00:34:14
desaparecen y se acabó
00:34:16
Bueno, pues podríamos completar esta aplicación de tal manera que cuando la aplicación arranca, recoja los alumnos de un fichero de texto, si es que los hay, para partir ya con ellos y cuando la aplicación termine, que todos esos alumnos vayan a un fichero, por ejemplo.
00:34:17
Y así, si nosotros apagamos la aplicación, apagamos el ordenador, no pasa nada cuando la aplicación arranque de nuevas, pues los alumnos seguirán estando exactamente los mismos.
00:34:39
Entonces, como lo que tenemos que guardar son objetos, aquí no podemos hacer ni FileWriter ni nada, esto es un lío.
00:34:52
Entonces tenemos que usar estas clases de serialización.
00:35:01
Vale, pues por ejemplo
00:35:04
Vamos a hacernos un método
00:35:06
Se puede copiar un proyecto entero
00:35:07
Si, si haces copy paste
00:35:13
Copy luego paste
00:35:15
Te lo copia con
00:35:18
Pero si yo lo
00:35:19
Hice el otro día, si, a ver
00:35:20
Copias
00:35:23
Y ahora yo pongo aquí paste
00:35:26
Y me aparece aquí
00:35:28
Otro con, me pone el 2 pero lo puedes cambiar de nombre
00:35:29
Vale, pues venga
00:35:32
vale, pues vamos a añadir un método
00:35:35
que de nuevo
00:35:40
puede ser interesante en este proyecto
00:35:42
que es guardar datos en fichero
00:35:44
guardar datos y ya está
00:35:46
guardar datos
00:35:47
y lo que le vamos a pasar es el nombre
00:35:57
del fichero en el que
00:36:00
queremos que se guarde
00:36:02
bueno, pues cuando llamemos a este método
00:36:03
toda esa lista
00:36:15
va a ese fichero
00:36:17
y ahí se queda preparada por si alguien quiere
00:36:18
recuperarla en algún momento, toda esa lista
00:36:20
de objetos alumna
00:36:22
vale, pues entonces
00:36:23
ahora lo que queremos es
00:36:25
escribir
00:36:28
escribir, recordad que tenéis que asociarlo a
00:36:30
muevo de variables
00:36:32
a fichero
00:36:35
eso es escribir, operación de escritura
00:36:36
operación de salida
00:36:38
las clases que tengan output
00:36:40
en su nombre, object, output string
00:36:43
file output string
00:36:45
o las que tengan writer
00:36:46
las que tengan
00:36:47
writer o output son las que hacen
00:36:50
escritura, que es llevar
00:36:52
de variables a fichero
00:36:54
y las clases que tienen en su nombre
00:36:56
input o reader son las que
00:36:58
hacen lectura, que es de fichero
00:37:00
a variables, en este caso
00:37:03
queremos escritura
00:37:04
de variables, de la lista en este caso
00:37:06
al fichero, escritura
00:37:08
pues entonces es object output string
00:37:10
esta es la que nos
00:37:12
interesa, hemos identificado
00:37:14
que queremos serializar objetos
00:37:17
llevarlos al fichero
00:37:18
pues esta es la que nos interesa
00:37:20
porque esta es la que nos vale para guardar objetos
00:37:22
pues venga, la podemos instanciar
00:37:24
y ahora
00:37:27
la paso aquí debajo
00:37:29
para que se vea bien
00:37:30
pues nada, se instancia aquí con el
00:37:32
constructor que sabemos que metemos
00:37:34
dentro
00:37:40
pero claro, el constructor
00:37:40
¿qué necesita?
00:37:43
pues el objeto de amputación es una clase
00:37:45
más compleja, obviamente
00:37:47
porque lo que tiene que hacer es meterse en el objeto
00:37:48
empezar a romper las propiedades
00:37:51
patatín patatán
00:37:53
y en última instancia esta clase a quien acabará llamando
00:37:54
a quien acabará llamando por debajo
00:37:57
es a la file output string
00:37:59
que hemos mencionado antes
00:38:01
porque esa es la básica
00:38:02
file output string es la que te lleva bits
00:38:03
de variable a fichero
00:38:06
pues el object output string está montada
00:38:08
sobre la file output string
00:38:11
cogiendo las variables, desmenuzándolas
00:38:12
poniéndolas en fila, haciendo todo el desmadre que haga falta
00:38:15
y en última instancia ya llamara a FileOutputStream
00:38:17
para que FileOutputStream las lleve.
00:38:20
Bueno, pues entonces el constructor necesita
00:38:23
que le pasemos como parámetro
00:38:25
el nombre del FileOutputStream,
00:38:28
el objeto, perdón, el objeto FileOutputStream
00:38:31
sobre el que queremos montarlo.
00:38:34
¿Y sobre qué FileOutputStream queremos montarlo?
00:38:36
Pues sobre uno que esté asociado a este, obviamente.
00:38:39
Entonces aquí para ahorrarnos referencias,
00:38:42
pues directamente le podemos pasar esto.
00:38:44
file output stream y
00:38:46
num fichero
00:38:51
entonces le estamos diciendo
00:38:53
al object output stream que todo
00:38:56
eso que él va a desmenuzar ahí
00:38:58
luego lo mande
00:39:00
a través de este file output stream
00:39:02
que este ya es el que manda los bits
00:39:04
directamente, que lo mande
00:39:06
a través de este que a su vez está asociado
00:39:08
a este fichero, pues nada
00:39:10
tendremos que importar las clases
00:39:14
y propagar la excepción
00:39:16
correspondiente, bueno
00:39:22
pues el uso
00:39:32
de esto en realidad es inmediato
00:39:33
porque object.outputString
00:39:36
lo único que te hace es
00:39:38
le pasas un objeto y te lo manda
00:39:39
y ya está
00:39:41
tiene un método
00:39:42
se puede usar para más cosas
00:39:44
tú le pasas aquí un objeto
00:39:51
una referencia
00:39:54
y te lo serializa y te lo manda
00:39:55
¿que quieres mandar muchos?
00:39:58
pues tendrás que hacer un bucle para que te los mande todos
00:39:59
aquí queremos mandar todos los que están en la lista
00:40:01
pues entonces tendremos que
00:40:04
meter aquí un for
00:40:06
¿vale? para recorrer esta lista
00:40:08
que se llama
00:40:10
alumnos
00:40:14
¿vale? pues
00:40:16
para cada objeto
00:40:22
alumno, para cada referencia
00:40:24
que está en alumnos
00:40:26
A es una copia
00:40:28
de la referencia, pero como
00:40:30
la copia de dirección de memoria va al mismo lado
00:40:31
bueno, no os olvidéis de que
00:40:34
el for each
00:40:36
es una copia de la referencia, pero
00:40:36
claro, apunta al mismo sitio
00:40:40
Pues que queremos hacer con este objeto
00:40:42
Ala, ya está
00:40:44
Pues ya está
00:40:45
Ya tenemos todos los objetos serializados
00:40:48
Un chorizo ahí de bits que ni idea
00:40:50
De como lo ha hecho, pero están ahí
00:40:52
Entonces una vez
00:40:54
Que uno ha terminado de guardarlos
00:40:56
Todos, pues
00:40:58
Lo cerraría ahí
00:41:00
Vale
00:41:03
Entonces vamos a probar desde nuestro main
00:41:05
Que tendremos aquí uno de pruebas
00:41:12
En el proyecto teníamos un main
00:41:13
sí
00:41:17
ejemplo alumnos
00:41:18
que estaba
00:41:23
aquí
00:41:25
vale, pues en este teníamos un main
00:41:31
para hacer pruebas
00:41:35
teníamos un insertar alumno, vamos a
00:41:36
dejarlo, va a insertar dos, este
00:41:39
y este
00:41:41
y luego teníamos aquí más pruebas
00:41:41
para comprobar que el alumno existía
00:41:44
matricular alumno
00:41:47
bueno, un montón de pruebas
00:41:49
de las funcionalidades que habíamos hecho
00:41:51
aquí más cositas
00:41:53
vale, vamos a dejar
00:41:57
nuestro main ahora mismo
00:42:01
con dos
00:42:02
que inserte a dos, para tener dos
00:42:06
y ahora
00:42:08
pues vamos a guardar los datos, entonces esto
00:42:10
claro, luego ya uno construye la aplicación
00:42:12
para guardar el momento que quiera
00:42:14
para si se ha dado la opción de salir
00:42:16
opción salir, quieres
00:42:18
pues este main tendría un
00:42:19
este main podría
00:42:22
tener un menú, ¿no?
00:42:24
un menú insertar alumno, no sé qué
00:42:26
y en la opción de salir
00:42:27
en la opción de salir, cuando el usuario de salir
00:42:29
pues en ese momento se llamaría guardar datos
00:42:31
en la de salir para que se queden guardados
00:42:34
pero bueno, como no tenemos
00:42:36
aquí el menú, vamos a insertarlos y a guardarlos
00:42:38
y la aplicación terminará
00:42:40
y ya está, habrá insertado a los alumnos y los guardará
00:42:42
pues venga
00:42:44
guardamos
00:42:46
datos, ¿en qué fichero? pues vamos a
00:42:48
pasarle un fichero de nombre
00:42:50
alumnos
00:42:51
guardar datos y esto como tiene
00:42:53
una excepción, pues me lo dice
00:42:58
No me lo dice porque entonces
00:42:59
Lo he debido poner mal
00:43:02
Ah, opera, ah, claro
00:43:03
Que no estoy en el mismo sitio, claro
00:43:05
Estoy en otra clase
00:43:07
Operaciones, vale
00:43:09
Y ahora ya sí que me dirá
00:43:12
Lo de la excepción
00:43:14
Ay, throws
00:43:15
Vale, pues vamos a parar aquí
00:43:19
Vale, un momentito
00:43:26
- Subido por:
- Raquel G.
- Licencia:
- Todos los derechos reservados
- Visualizaciones:
- 11
- Fecha:
- 25 de mayo de 2024 - 17:58
- Visibilidad:
- Clave
- Centro:
- IES ROSA CHACEL
- Duración:
- 43′ 31″
- Relación de aspecto:
- 1.78:1
- Resolución:
- 1920x1080 píxeles
- Tamaño:
- 177.54 MBytes