20250327 Persistencia Datos 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:
Vale, estoy grabando, por lo tanto si habláis me autorizáis a grabar vuestra voz.
00:00:00
Vamos a empezar hoy el concepto, a ver, unas pinceladas de persistencia de datos.
00:00:07
En realidad la persistencia de datos se divide en dos grandes partes, digamos.
00:00:12
Una es trabajar con ficheros y la otra sería la gestión, el acceso a las bases de datos.
00:00:19
¿Vale? El acceso a la base de datos
00:00:27
Históricamente en esta asignatura
00:00:29
Es la que dejamos al final
00:00:31
Y si no nos da tiempo
00:00:33
No pasa nada porque en segundo
00:00:35
Tanto si hacéis DAM como si hacéis DAW
00:00:37
Seguramente vais a
00:00:39
Ver algo de acceso
00:00:41
A base de datos desde
00:00:43
Programación, por lo tanto no es una cosa
00:00:45
Que hagas algo de aquí y no lo he visto nunca
00:00:47
Además nosotros según
00:00:49
Esto no lo debería grabar
00:00:51
No lo grabo
00:00:56
Vale, entonces, dos grandes áreas, no me acuerdo si le había dicho o no, ¿vale? Después de esta pausa que quién sabe qué se ha dicho. Pues, uno son los ficheros, la otra es la base de datos. Sí, le había dicho, ¿vale? Entonces, empezamos con conceptos un poco genéricos, luego vamos a ver, empezar un poquito cómo se usa un fichero y cómo se guarda el fichero.
00:01:00
No es difícil, es bastante sencillo.
00:01:20
Ahora, algunas cosas se pueden complicar, hay algunos peligros y problemas que surgen por allí.
00:01:25
Tened en cuenta que nosotros llegaremos hasta un punto que será guardar objetos en un fichero,
00:01:34
para que luego cuando lo necesitemos lo podemos volver a pillar, y esto no es lo que se hace hoy en día.
00:01:41
Lo que vamos a aprender aquí es una base, es una idea básica que puede servir para mueblar nuestra cabeza, pero hoy en día nadie se soñaría en un proyecto serio de hacerlo como lo vamos a hacer nosotros.
00:01:47
Hoy en día hay plugin, hay herramientas, hay mecanismos más avanzados que aprenderéis el próximo año o en los años siguientes de gestión de la cosa.
00:02:05
Como por ejemplo, a lo mejor a alguien se os suena, Hibernate. Es una forma de gestionar la cosa. Tú tienes que configurar tu proyecto con varias cosas que no son triviales y una vez que lo has hecho, pues lo que haces es le dices a ellos, mira, guárdame estos ficheros y él lo guarda.
00:02:21
¿Vale? Pero hay que saber qué hacer.
00:02:41
¿Vale? Y entonces todavía es pronto.
00:02:43
Pero sí, que
00:02:45
lo que es guardar datos
00:02:46
en ficheros y luego sacar ficheros
00:02:48
de allí, pues sí que puede servir.
00:02:51
¿Vosotros no habéis visto, todavía me habéis dicho
00:02:52
XML? ¿Vale?
00:02:54
Pero, por ejemplo, lo que sí
00:02:57
el XML
00:02:58
es una cosa que
00:03:00
que hay gente
00:03:02
que la ama y hay gente que la odia.
00:03:05
¿Vale? Hay gente que dice la cosa peor
00:03:06
que ha pasado la informática. Hay gente que
00:03:08
dice no porque no se puede utilizar pero con lo que vemos ahora sí que se puede
00:03:10
trabajar con xml que queriendo creando xml o leyendo xml por ahora dejando
00:03:17
aquí aparcado lo veréis xml deberías empezar ahora porque tampoco queda
00:03:23
mucho tiempo no vais a ver xml vais a ver xml casi seguramente porque es una
00:03:27
parte importante de lenguaje de marcas o sea si habéis visto html pues igual html
00:03:37
solo que te inventas las etiquetas y ya está hemos dado xml pues ya está vale el código
00:03:43
programación orientado al objeto vale nosotros sabemos que es un objeto a este punto de nuestra
00:03:51
vida sabemos cómo definimos un objeto como definimos un objeto con una clase vale definiendo
00:03:58
una clase es una generalización de los objetos que luego voy a crear voy a definir los atributos los
00:04:09
métodos que pueden, o sea, los comportamientos de estos objetos
00:04:16
y por lo tanto para definir un objeto lo que se hace es definir
00:04:19
su generalización, su abstracción, ¿vale? que sería la clase
00:04:23
y luego a partir de ahí crea objetos concretos que podrán hacer
00:04:27
lo que he establecido en la cosa, ¿vale? El código que yo
00:04:31
escribo, compilado, etcétera, etcétera, se guarda normalmente
00:04:35
¿dónde? El código que yo escribo y que luego compilo
00:04:39
en Java, etcétera, etcétera, ¿dónde se guarda?
00:04:46
disco duro
00:04:51
¿vale? cosa interesante porque
00:04:52
tú cuando escribes tu programa
00:04:54
lo ejecutas
00:04:56
le haces el Java C
00:04:57
entonces obtienes el bytecode
00:05:00
¿vale? los puntos clases, cosas por el estilo
00:05:02
esos
00:05:04
ficheros, esa parte
00:05:05
ese código no se pierde
00:05:08
tú apagas el ordenador
00:05:10
lo enciendes otra vez y ese código
00:05:12
no se ha perdido
00:05:14
¿qué se pierde entonces entre apagar
00:05:15
y encender el ordenador otra vez.
00:05:18
Objetos y variables.
00:05:32
Esos sí son los que estamos perdiendo ahora mismo.
00:05:35
El código es el mismo, pero cada vez que lo enciendes
00:05:38
como si empezaras desde cero.
00:05:40
Si claramente en mi código hay una parte de inicialización
00:05:42
que me crea 300 alumnos en código,
00:05:46
que es una idea bastante fea,
00:05:49
pero si lo hace, cada vez que lo arrancare
00:05:51
me crearé estos 300 alumnos.
00:05:54
Pero los objetos que estoy creando
00:05:56
se están creando, ¿dónde? En la RAM.
00:05:59
En particular en una área de la RAM, que es un trozo de la RAM
00:06:03
que se dedica al proceso que yo estoy lanzando. Cuando yo ejecuto
00:06:07
la Java Virtual Machine, será un proceso que es el intérprete
00:06:12
y luego tendrá mi proceso, mi hilo de ejecución, que tendrá asociado
00:06:16
un trozo de memoria. ¿Vale? Entre procesos no se
00:06:20
comparte memoria. Entre threads sí. Es la diferencia que
00:06:23
entre procesos y threads, y si queréis saber más, en segundo de DAM.
00:06:27
Entonces, cuando yo creo objetos y variables, estos objetos y variables se guardan en RAM.
00:06:33
La RAM es la memoria principal, la memoria más rápida, más cara también,
00:06:40
pero tiene la cuestión de que si no tiene electricidad, todo lo que está en RAM se pierde.
00:06:45
Entonces, entre una ejecución y otra, o entre un encendido y otro del ordenador,
00:06:50
todo lo que estaba en la RAM, lo pierdo
00:06:56
¿vale? o sea que los datos
00:06:58
en RAM no persisten
00:07:00
para que persistan
00:07:01
tengo que utilizar el disco
00:07:03
duro, ahora vosotros sabéis
00:07:06
de sistemas informáticos que la RAM
00:07:07
va rápida y es bonita, pues el disco
00:07:10
duro es súper lento, cada vez que toco
00:07:12
el disco duro
00:07:14
ralentizo muchísimo
00:07:15
mi programa
00:07:17
de hecho, si vosotros tenéis
00:07:19
poca RAM en vuestro ordenador
00:07:22
y encendéis varios
00:07:23
programas, el navegador
00:07:25
luego un juego, luego no sé qué
00:07:28
llega un momento en que todo va súper lento
00:07:30
¿por qué va todo súper lento?
00:07:32
porque yo necesito trabajar
00:07:47
los programas trabajan con la RAM pero no hay suficiente
00:07:50
RAM para todos y entonces
00:07:52
los procesadores normalmente
00:07:54
hoy en día hacen lo que se llama programación
00:07:58
concurrente, o sea que
00:08:00
hay pocos recursos de procesamiento
00:08:02
un procesador con
00:08:04
cuatro núcleos
00:08:06
por ejemplo, pues eso quiere decir que puedo ejecutar cuatro hilos, cuatro hilos de ejecución
00:08:08
en cada momento. Ocho si tengo multitrading que hace cosas raras, pero me da igual. O
00:08:14
dieciséis si tengo un procesador más potente. Pero la cuestión es que eso son los que se
00:08:19
pueden ejecutar. Ahora, ¿qué pasa? El procesador los va cambiando constantemente, uno y otro,
00:08:23
uno y otro, dándome la ilusión que estén viendo todos a la vez. Pero en realidad, paralelismo
00:08:28
verdadero, pues solo lo puede hacer con muy pocos
00:08:34
procesos, con muy pocos threads, porque son los threads
00:08:37
que tengan los núcleos que puede ejecutar
00:08:40
¿vale? Ahora, si no tengo RAM suficiente
00:08:43
cada vez que un proceso llega al procesador
00:08:46
y tiene que ser ejecutado, quiere encontrarse los datos
00:08:49
en la RAM, pero si no hay espacio para todos
00:08:52
el sistema operativo empieza a hacer operaciones de swapping
00:08:55
o sea, pillo lo que está en la RAM
00:08:59
Libero una parte de la RAM de otro proceso
00:09:01
Que en este momento no se está ejecutando
00:09:05
Y lo copio en el disco duro
00:09:07
Voy a pillar lo que había copiado tuyo en el disco duro
00:09:08
Y lo copio en RAM
00:09:12
Y esto se está haciendo constantemente
00:09:13
Ahora como el disco duro es lento
00:09:15
Pues todo empieza a ir muy muy lento
00:09:18
Porque cada vez que hago esta operación de swapping
00:09:20
Pues esto es muy lentísimo
00:09:23
¿Sí?
00:09:25
Vale
00:09:27
Entonces, también el código que yo ejecuto se guarda en RAM
00:09:27
O sea, eso está guardado en el disco duro
00:09:34
Pero cuando ejecuto al principio el programa
00:09:37
Copio desde disco duro las instrucciones a RAM
00:09:40
Porque luego cuando se ejecuta RAM tiene que estar en RAM
00:09:44
Y luego todos los niveles de caché que vosotros conocéis
00:09:47
Siempre más cerca del procesador
00:09:51
Hasta llegar a la memoria más pequeña y más rápida
00:09:53
que son los registros del procesador
00:09:56
¿sí?
00:09:58
entonces, hemos dicho que nuestros
00:10:00
objetos en estas variables no persisten
00:10:02
se acaban, ¿vale?
00:10:04
los valores de atributos
00:10:07
de los objetos no persisten previamente en el disco
00:10:08
¿vale? cuando hago una new
00:10:10
se crea un nuevo
00:10:12
en un trozo de la rama, un nuevo objeto
00:10:14
y este trozo de la rama
00:10:16
se llama heap
00:10:18
mucio, ¿vale?
00:10:19
no, mucio es italiano, montón
00:10:22
es español, ¿sí?
00:10:24
los objetos se crean en esta zona
00:10:26
porque es una zona que funciona un poquito distinta
00:10:30
con como se crean en vez de las variables
00:10:33
que es otra zona que ahora vemos
00:10:35
y entonces no tiene el mismo funcionamiento que el otro
00:10:36
no sabría definiros bien
00:10:41
como funciona el heap de Java
00:10:45
sepáis simplemente que es otro tipo de
00:10:51
estructura datos dinámica
00:10:54
¿vale? no es
00:10:57
una cola, no es una pila
00:10:58
no es una lista
00:11:00
es otra forma de organizar
00:11:02
los datos allí, con muchas referencias
00:11:04
porque vosotros sabéis que los objetos tienen
00:11:06
toda esta cosa de referencias
00:11:08
etcétera, etcétera, ¿vale?
00:11:10
por otro lado, en vez de las variables locales
00:11:12
los parámetros, cuando llamo un método
00:11:14
y cosas por el estilo, se guardan en una zona
00:11:16
de memoria que se llama la stack
00:11:18
¿vale? que es esta pila
00:11:20
y vosotros sabéis que es una pila, ¿vale?
00:11:22
Entonces, cuando nosotros, ¿os acordáis el concepto que vimos al principio de curso de ámbito de una variable? El scope, ¿vale? Que una variable solo existe en el bloque en el que la declaro, ¿vale? Y muchas veces los bloques se relacionan también con métodos.
00:11:24
O sea, un método al fin y al cabo es un bloque. Yo llamo desde aquí y cosas por el estilo. Entonces existe esta pila que sustancialmente va apilando las nuevas llamadas de métodos o los nuevos bloques que se crean y allí en cada nivel de la pila crea las variables.
00:11:44
De esta forma que cuando se acaba un bloque, entonces todas las variables que estaban en ese nivel de la pila, se hace una pop en la pila, se quita la cabeza de la pila y todas esas variables ya no existen.
00:12:03
Es la razón de por qué existen las variables locales.
00:12:18
Tú dentro del bloque las declaras, declaras dentro de un for una int i, usas i todo lo que te da la gana dentro del for, pero cuando sale del for ya i no existe.
00:12:21
Si la necesito fuera de IMET, la tengo que guardar en algún lado o declararla fuera del FOR para que valga en el nivel más bajo de la pila.
00:12:31
¿Se entiende?
00:12:41
Vale.
00:12:43
Entonces, todo esto a nivel de RAM.
00:12:44
Cuando apago, enciendo o acabo la ejecución, se pierde todo.
00:12:46
¿Vale?
00:12:50
Cuando finaliza el programa, los datos de los atributos del IP y también algunos de los TAC, pues, no persisten.
00:12:51
¿Vale?
00:12:57
Aunque en muchos casos sería deseable.
00:12:58
¿Vale?
00:13:00
Lo que hemos hecho siempre, por ejemplo, con el alumno, pero puede ser con cliente, puede ser con coche, todo lo que yo he creado. Imaginaos las cosas que estáis haciendo ahora con Graphical User Interface, que ponéis los datos y los grabáis. Pues estáis creando cosas. No quiero que cada mañana que empiece a trabajar en mi empresa tenga que volver a grabar todos los datos de los clientes para poder trabajar con ellos.
00:13:01
entonces, no se existe
00:13:23
un mecanismo
00:13:26
automático de persistencia
00:13:28
en la mayoría de los lenguajes
00:13:30
de un reto de objetos, en particular
00:13:32
en Java, no existe algo
00:13:34
automático que dice
00:13:36
si ahora se va la luz, pues estaba
00:13:38
guardando todo en el disco duro y no he perdido
00:13:40
nada, lo tengo que hacer yo
00:13:42
manualmente, en el sentido, no
00:13:44
necesariamente soy yo el que va a escribir
00:13:46
ceros y unos con un
00:13:48
imán en el disco duro
00:13:50
¿Vale? Pero si soy yo que le tengo que decir en un determinado momento, este es el momento en el que tu programa, haz tu magia y guárdame estos datos que te paso en un fichero.
00:13:51
¿Sí? Si los guardo bien y lo hago bien, mañana cuando enciende mi ordenador, pues posiblemente siguen allí.
00:14:05
Si lo has escrito en formato texto, los puedo hasta mirar yo. Si lo he escrito de otro formato, puedo ir a mirar, pero veré estas cosas raras que hace alguna vez cuando abrís un fichero con el Notepad y hay carácteres que no son texto, ¿vale?
00:14:12
Entonces, dependiendo de allí, ahora lo veremos también, nosotros podremos escribir en fichero y decidir si escribimos bytes, entonces puede ser cualquier cosa, o si escribimos caracteres.
00:14:28
Entonces ya tengo algunas limitaciones porque estoy escribiendo caracteres y no cualquier cosa como un byte o cosa por el estilo.
00:14:42
Si estoy copiando y trabajando con ficheros de textos, utilizaré char y string y lo que sea, si los ficheros con los que estoy trabajando no están pensados para ser inteligibles, para ser humanos, entonces no son de tipo texto, pues debería trabajar con bytes.
00:14:48
porque si no, podría ser que un char no se corresponda exactamente a los bytes que estoy leyendo.
00:15:12
Y entonces podría ser que cuando voy a leer, yo leo en grupos para traducirlos en char,
00:15:21
y pues un grupo se queda en mitad porque allí acababa el byte o acababan los ficheros que estaba mirando.
00:15:26
Un ejemplo de ficheros que no utilizan cosas son los ejecutables.
00:15:32
Todos los ficheros que son .exe, si vosotros intentáis abrirlos con un bloc de notas, pues veis que no se entiende porque esos son ceros y unos que se interpretarán por el procesador.
00:15:37
Entonces, no son caracteres. Entonces, cuando lo voy a interpretar, el bloc de notas intenta interpretarlo como caracteres, salen cosas raras.
00:15:52
almacenamiento de datos
00:16:01
¿cómo conservamos valores de datos
00:16:05
en un dispositivo de almacenamiento
00:16:08
y cosas por el estilo? pues hay varias opciones
00:16:10
¿vale? opción número A
00:16:12
creando un archivo
00:16:14
¿vale? que es lo que veremos nosotros
00:16:16
entonces nosotros tenemos en nuestro oficiero
00:16:18
le guardamos los datos en modo
00:16:20
RAW, en modo crudo
00:16:22
en modo tal cual son
00:16:24
¿vale? lo guarda allí o en modo texto
00:16:26
¿vale? o en
00:16:28
Voy a copiar los ceros y unos
00:16:29
Que será este objeto
00:16:31
Al fin y al cabo todo en informática son ceros y unos
00:16:33
Entonces yo puedo
00:16:35
Trabajar con ceros y unos
00:16:37
Que sería el modo row
00:16:38
Y entonces mi objeto será una tira de ceros y unos
00:16:40
Pues copio estos ceros y unos en un fichero
00:16:43
Pues ya está, tengo mi objeto guardado
00:16:45
O si no, en modo texto
00:16:47
Veremos los dos ejemplos
00:16:50
También puedo tirar de la Java Virtual Machine
00:16:52
Y decir, Java Virtual Machine
00:16:56
Mira, yo te doy un fichero
00:16:57
Luego te doy un objeto, guárdamelo tú. Haz tu magia, haz lo que tienes que hacer. Yo no quiero saber cómo lo guardas, qué estás haciendo por debajo. Estoy abstraendo el cómo se hace, te estoy diciendo qué hacer.
00:16:59
Entonces, tengo este objeto, por favor guárdamelo tú, ¿vale? No todos los objetos se pueden guardar, hay características que tengo que tener en cuenta y cuidado porque la cosa se puede complicar, ¿vale? Esto se llama normalmente la serialización de un objeto, transformar un objeto en una serie de ceros y unos que pasaré al disco duro y que lo guardaré allí, ¿vale?
00:17:15
Veremos que para que un objeto sea guardado en un disco duro
00:17:40
Tiene que implementar la interfaz
00:17:44
Serializable
00:17:46
Serializable
00:17:48
No sé cómo se pronuncia
00:17:51
¿Vale?
00:17:52
Otra opción es
00:17:54
Molestar a las bases de datos
00:17:56
¿Vale?
00:17:59
Entonces decir a las bases de datos
00:18:00
Oye, mira, como son muchos datos los que tengo que gestionar
00:18:01
Y el disco duro no está optimizado para esto
00:18:04
voy a buscar a alguien que está especializado en guardar datos
00:18:07
y le digo, oye, mira, guárdame estas cosas, ¿vale?
00:18:11
A partir de allí se puede guardar de distintas formas,
00:18:14
como en unas tablas que tenga columnas distintas
00:18:17
y por cada columna tenga un atributo del objeto
00:18:22
y que yo guarde allí en cada columna su objeto,
00:18:25
o pueda utilizar un blob o lo que sea
00:18:28
para guardar enteros los objetos por ahí, ¿vale?
00:18:30
si necesito mucho esto
00:18:34
entonces tengo programas que necesitan guardar
00:18:38
y recuperar muchos de estos
00:18:41
objetos, pues posiblemente montaré
00:18:43
algunos de estos mecanismos como Evernate o cosas por el estilo
00:18:47
que me permite trabajar con
00:18:50
la base de datos y hacerlo rápidamente
00:18:53
nosotros por ahora no
00:18:55
vale, entonces empezamos a ver que nos hace falta
00:18:58
para poder trabajar con Java y hacer cosas con ficheros?
00:19:02
Pues la primera es la clase File, ¿vale?
00:19:07
Existe la clase File que ya existe en java.io, ¿vale?
00:19:10
Paquete de input-output, ¿vale?
00:19:14
Entonces es una clase que abstrae y representa un fichero.
00:19:17
Cuidado, no es un fichero, es un manejador de fichero, ¿se entiende?
00:19:24
Es como a nivel de Java
00:19:28
Puedo referenciar un fichero
00:19:31
Luego el fichero estará en el disco duro
00:19:35
Y será otra cosa
00:19:37
Pero si yo tengo que saber
00:19:38
Por ejemplo, preguntarme cosas como
00:19:40
Si este fichero ya existe
00:19:42
Si este fichero tiene dentro datos
00:19:44
O cosas por el estilo
00:19:47
Necesito un handler, un manejador
00:19:48
Desde la perspectiva de Java
00:19:51
Para poder decir
00:19:53
Este es un objeto que representa este fichero
00:19:54
ahora te hago preguntas a ti objeto y tú harás lo que sea para ir a mirar en el disco duro
00:19:56
si efectivamente estas cosas son verdaderas, son falsas, cuánto ocupas, etc.
00:20:02
El punto, es siempre lo que hacemos en Java al fin y al cabo, es intentar extraer cosas más o menos físico-reales.
00:20:08
Nosotros no queremos trabajar directamente con los discos duros y decirle
00:20:18
ponte a girar o ponte a buscar niveles de energía de donde has guardado en el SSD el fichero,
00:20:21
pues no me interesa, pues a mí me interesa extraer, decirle, oye, mira, esto es un fichero, vale,
00:20:28
ahora represento un fichero, usámoslo, ¿vale?
00:20:33
Para crear o abrir un fichero, en Java se invoca un constructor de la clase File, ¿vale?
00:20:36
Entonces yo creo un new file y ese de allí me crea ya el constructor.
00:20:41
Si quiero estar seguro que exista, está también una función de create file, si no existe,
00:20:44
Y existe un otro método que es el exists, que me devuelve true si el fichero ya existe y false si no, ¿vale? Entonces, una cosa estándar es crear el fichero como objeto, comprobar si ya existe, si ya existe lo utilizo, si no existe lo creo o lo relleno o doy un error, dependiendo de lo que quiero hacer, ¿vale?
00:20:50
Si estoy haciendo un programa donde está una serie de datos de inicialización, entonces tengo un fichero de init donde dentro pongo los datos iniciales de mi programa y este fichero no está, podría simplemente decir, oye, mira, tengo un problema, no existe el fichero init.
00:21:12
Si os acordáis, no nos ha pasado a nosotros un error cuando Manoli instaló la base de datos, nuestro programa Eclipse dejó de funcionar y que había que buscar un fichero .ini y cambiarle la cosa allí, que .ini de inicialización, porque allí no encontraba la Java Virtual Machine correcta.
00:21:30
¿No? ¿Sí? ¿Pasado este año? Pues yo creo que sí, pero no me acuerdo. Vale, entonces, una vez que tengo el fichero file, pues necesito trabajar con flujos de información, streams, ¿vale? Y tengo input stream y output stream.
00:22:02
Los output stream son los que escriben en el fichero, los input stream son los que leen de fichero.
00:22:21
La perspectiva es de mi programa, ¿vale? Entonces si yo estoy en mi programa, lo que es output es cosas que salen de mi programa y van fuera de mi programa, por ejemplo en un fichero.
00:22:31
Input son cosas que están fuera de mi programa y yo quiero leer para introducirlos en mi programa.
00:22:42
Entonces, cuando yo quiero salvar los datos, necesitaré un output stream para poder escribir los datos en memoria secundaria. Cuando enciendere mi programa otra vez y será un programa nuevo y quiere leer esos datos, necesitaré un input stream para poder leer desde ese lado.
00:22:48
¿Se entiende más o menos? El input stream es el más, y output stream son los niveles más bajos que podáis encontrar en Java. Si hurgáis, pues encontráis cosas más bajas, pero lo que usamos nosotros.
00:23:08
Es decir, que son los que están más cercanos a los ceros y unos, a los bytes que quiero leer. Por eso, las funciones que me proporciona InputStream y OutputStream son funciones de bajo nivel.
00:23:23
de escríbeme este byte en el fichero, léeme un byte, ¿vale?
00:23:41
Estamos trabajando con byte, no estamos trabajando con string,
00:23:47
no estamos trabajando con objetos.
00:23:49
Se lee byte por byte, se escribe byte por byte.
00:23:51
Y vosotros podéis hacer absolutamente todo a este nivel.
00:23:54
Ahora, ¿cómo es aburrido?
00:23:59
Porque, por ejemplo, si tú lees un entero, en vez de leer un entero,
00:24:01
deberías leer cuatro bytes y luego mezclar los estos bytes
00:24:05
y hacer un único entero grande
00:24:09
y a ese punto interpretarlo como un entero
00:24:11
si es un double son 8, si es un char
00:24:13
no lo sé, son 2, 1, cuánto es
00:24:15
pues sería complejo
00:24:17
pues hay
00:24:19
clases
00:24:21
que van subiendo el nivel
00:24:22
de abstracción que me crean
00:24:25
nuevos
00:24:27
métodos que se puedan
00:24:28
utilizar para sostancialmente
00:24:31
en vez de trabajar byte por byte
00:24:33
trabajar con cosas un poquito más
00:24:35
fáciles para los seres humanos
00:24:36
Entonces, InputStream encapsula un flujo de bits para leer, que pueden provenir del teclado, de un fichero, de una conexión de red, etc. El escáner probablemente por dentro tiene un InputStream o parecido, que lo que hace es leer la información que llega desde el teclado.
00:24:38
Pero para nosotros es una abstracción y nosotros no lo vemos.
00:25:01
No hemos creado InputStream, pero será.
00:25:04
La cosa interesante es que con InputStream tú lees desde cual sea la fonte que llegas.
00:25:07
Este año lo usamos para ficheros.
00:25:14
Si llegáis en segundo de DAM, pues lo usaremos para conexiones de red para los sockets.
00:25:16
Y es lo mismo. Es exactamente esta misma clase.
00:25:22
Tanto aquí como allá.
00:25:26
Es simplemente una clase que me permite leer bytes y guardarlos en una red de bytes.
00:25:27
Ahora, si no quiero trabajar con bytes, ¿por qué lo que estoy trabajando son mensajes de texto?
00:25:33
¿Por qué los ficheros que estoy utilizando son ficheros de texto?
00:25:42
¿Por qué no estoy trabajando con ficheros que no son inteligibles para los seres humanos?
00:25:45
y por lo tanto necesito que sean interpretados como carácteres,
00:25:56
en vez de utilizar un inputStream, podría utilizar un inputStreamReader.
00:26:00
Cuando está la palabra reader o writer, es que no estoy trabajando byte por byte,
00:26:07
sino que estoy trabajando con char, con carácteres.
00:26:14
Si tiene este reader, tiene esta funcionalidad extra.
00:26:17
Como yo asumo
00:26:22
Que ahora no estoy trabajando byte con byte
00:26:23
Pero asumo que estos sean caracteres
00:26:26
Puedo crear
00:26:28
Nuevos metodillos
00:26:30
Que ya asuman esto
00:26:31
Que ya digan, ah vale, cuando leo
00:26:34
No voy a leer un byte
00:26:36
Sé que voy a leer un char
00:26:37
Por lo tanto, la respuesta al read
00:26:39
No será que te devuelvo
00:26:42
Un array de byte
00:26:44
A lo mejor te devuelvo un array de char
00:26:45
¿Vale? Teniendo en cuenta que
00:26:47
De todas formas, un array stream reader
00:26:49
un inputStreamReader como veremos
00:26:52
como parámetro del
00:26:53
constructor pilla un inputStream
00:26:55
o sea que es sustancialmente
00:26:58
un involucrar
00:26:59
un rapear
00:27:02
no lo sé como decirlo
00:27:03
pillar algo que solo
00:27:06
tiene metodillos básicos de leer byte por
00:27:09
byte y decir vale te extendo
00:27:11
en un cierto sentido, no es una extensión
00:27:13
en términos de
00:27:15
herencia pero por ahí
00:27:17
voy a hacer cosas
00:27:19
más utilizando tus métodos porque
00:27:21
quien luego al final lee será siempre inputStream
00:27:23
pero ya me creo los métodos
00:27:26
que dice, leo los bytes suficientes
00:27:27
lo interpreto como char y por lo tanto
00:27:30
ahora trabajo con char, ese es un reader
00:27:32
¿vale?
00:27:33
y en particular tenemos el fileInputStream
00:27:35
y el fileReader que son
00:27:38
digamos, métodos
00:27:39
clases que permiten
00:27:42
trabajar con ficheros
00:27:44
¿vale? entonces nosotros
00:27:45
normalmente tendremos un fileInputStream
00:27:47
que tiene dentro un
00:27:50
inputStream como parámetro
00:27:51
Vosotros que ya habéis entendido
00:27:53
Cómo funciona la vida del programador
00:27:57
Como yo os estoy nombrando
00:27:59
Estas clases
00:28:01
Hoy por la tarde cuando os aburrís
00:28:03
Que no tenéis nada de mejor que hacer
00:28:05
Os abrís el API
00:28:07
Vais a mirar InputStream, InputStreamReader
00:28:08
Y veis la diferencia
00:28:11
Y veis que pueden hacer uno y otro
00:28:12
Para que luego a partir de mañana
00:28:15
Sepáis cuando usar uno
00:28:16
Y cuando usar el otro
00:28:19
Subiendo todavía a nivel más alto todavía, tenemos nuestro amigo el Buffered Reader.
00:28:22
El Buffered Reader es un reader, es parecido al otro, que añade la posibilidad de crear un buffer.
00:28:28
¿Qué es un buffer? Es una memoria temporal.
00:28:36
Es decir, que en vez de estar leyendo uno a uno los caracteres o los bytes o lo que sea,
00:28:38
yo puedo crearme una memoria temporal y guardar allí los caracteres.
00:28:45
Esto me permite crear métodos más útiles, más cómodos para nosotros los programadores
00:28:49
Como por ejemplo, puedo leer una línea entera de golpe
00:28:58
Mientras usando este de aquí, tengo que leer carácter por carácter
00:29:02
Esperando al carácter que sea retorno de carro, el barra n
00:29:07
Para decir, aquí se acaba la línea
00:29:12
pues usando la clase BufferedReader le puedo decir usar la operación ReadLine
00:29:14
que lee una línea entera y me la devuelve como un string, ¿vale?
00:29:20
Entonces si yo estoy guardando en mi fichero los datos línea por línea
00:29:24
pues utilizar un BufferedReader y leerlo línea por línea puede ser una opción, ¿vale?
00:29:33
Una de las formas que nosotros usaremos esto es que cada objeto que nosotros guardaremos
00:29:38
lo guardaremos en un formato textual, ¿vale? En una representación textual del objeto mismo y lo guardaremos un objeto por línea.
00:29:43
De esta forma, cuando luego voy a leer el fichero, lo que voy a hacer es leer de golpe una línea y allí ya tengo todos los datos del primer objeto.
00:29:53
Y ahora me lo voy parceando, me lo voy troceando, buscando cuál es el valor del primer atributo, el valor del segundo, para reconstruir el objeto.
00:30:02
es una de las formas que se puede hacer
00:30:11
y que veremos
00:30:13
vamos a leer un archivo de texto
00:30:15
¿vale? entonces se utiliza
00:30:18
una clase java.io
00:30:19
file reader y la java.io
00:30:21
buffered reader ¿vale? entonces
00:30:23
file reader fr es igual a
00:30:25
null, buffered reader br es igual a
00:30:27
null, pues esto se podría hacer directamente
00:30:30
aquí, pero me da igual
00:30:31
fr es igual a new file reader
00:30:33
de una ruta del archivo
00:30:36
¿vale? esta cosa de aquí crea
00:30:37
un nuevo file reader, que es un lector, entonces estamos hablando de char especializado en
00:30:39
ficheros, y aquí le pongo el nombre del fichero. Paréntesis sobre las rutas. Vosotros sabéis
00:30:46
que en el mundo de la informática hay dos tipos de rutas, las rutas absolutas y las
00:30:55
rutas relativas, ¿vale? ¿Dónde me espero que exista el fichero que voy a leer si no
00:31:01
le pongo ninguna ruta? Si aquí pongo mi fichero.txt, ¿dónde aparecerá ese fichero? No. Sí o
00:31:10
No, quién sabe.
00:31:24
En el Eclipse es el proyecto.
00:31:26
No source, no bin, el proyecto.
00:31:31
Esa es considerada la working directory.
00:31:36
Cuando yo busco un fichero sin decirle nada, lo busco allí.
00:31:39
Si esto es un proyecto, el proyecto, no, es el disco duro que tiene que empezar a girar.
00:31:44
Si yo tengo un proyecto, mi lista, qué sé yo
00:31:57
Aquí es donde se acerca el fichero
00:32:01
¿Vale?
00:32:04
No en source
00:32:06
No en bin
00:32:07
¿Vale?
00:32:09
Tened en cuenta que vosotros no lo pensáis
00:32:11
Pero vosotros editáis esto
00:32:13
Pero no ejecutáis esto
00:32:16
Ejecutáis siempre esto
00:32:18
Vosotros estáis ejecutando los .class
00:32:20
¿Vale?
00:32:23
El eclipse en automático
00:32:24
Cada vez que vosotros guardáis
00:32:26
Pilla vuestro punto Java
00:32:28
Le hace una compilación
00:32:30
Y guarda los puntos class
00:32:32
En esta carpeta de aquí
00:32:34
Tiene la misma estructura
00:32:35
Aquí está el paquete mi lista
00:32:37
Aquí tendrá el paquete mi lista también
00:32:39
Tiene la misma estructura del source
00:32:42
Pero no se ejecuta el source
00:32:45
Se ejecuta en el bin
00:32:46
Si este fichero de aquí
00:32:47
Le diera un
00:32:52
Si este class de aquí
00:32:53
leyera un fichero, me esperaría
00:32:56
que el fichero tuviera que estar aquí
00:32:58
¿vale? y si yo lo
00:33:00
lanzo con Java
00:33:02
directamente a esta clase
00:33:03
desde esta carpeta, posiblemente
00:33:06
debería estar aquí, ¿vale?
00:33:08
pero a nivel de Eclipse
00:33:09
Eclipse lo va a buscar aquí, esta es su
00:33:11
working directory, digamos que
00:33:14
el punto donde arranca
00:33:15
él piensa de estar en esta
00:33:17
directory de aquí, yo puedo crearme
00:33:19
aquí una carpeta que se llame ficheros
00:33:22
y poner ahí dentro los ficheros
00:33:24
O cosas por el estilo
00:33:25
Es un error enorme
00:33:26
Colosal
00:33:29
Y os suspendo instantáneamente
00:33:30
Si me ponéis algo así
00:33:32
No puedo hacerlo más grande
00:33:35
Porque luego se me bloquea la cosa
00:33:42
Como de dos puntos, barra, prog
00:33:44
24, 25, barra, mi lista
00:33:46
Es decir, una ruta
00:33:48
Absoluta
00:33:49
Las rutas absolutas no se usan
00:33:50
¿Por qué?
00:33:53
¿Sí? ¿Se entiende?
00:33:58
Es lo mismo que os pasa en HTML
00:34:00
cuando vosotros tenéis HTML o el CSS
00:34:02
si le ponéis la ruta relativa
00:34:05
y luego copiáis la carpeta en otro ordenador
00:34:08
os funciona perfectamente
00:34:11
si le habéis puesto la ruta absoluta
00:34:12
y lo lleváis a otro ordenador
00:34:14
que no tiene exactamente vuestra ruta
00:34:16
pues no va a funcionar
00:34:18
y esto os pasa muchas veces
00:34:19
porque vosotros trabajáis siempre solo en el mismo ordenador
00:34:21
luego lo subís al servidor
00:34:23
que este paso no lo estáis haciendo todavía
00:34:25
pero lo subís al servidor y no funciona nada
00:34:27
porque habéis puesto esta cosa aquí
00:34:29
es suspenso automático
00:34:31
Entonces, con esta de aquí me he creado un file reader
00:34:32
Dejad de hablar vosotros dos
00:34:40
Es 20 minutos, quiero reís de no sé qué
00:34:42
Sí, vosotros dos
00:34:45
Vale, entonces, con esto he creado el file reader
00:34:50
El file reader es esta cosa que me permitiría leer
00:34:53
¿Vale? Leer carácter por carácter es de un fichero
00:34:56
Es una clase de ese estilo
00:34:59
Pero yo quiero leerme una fila entera, una línea entera
00:35:00
Entonces, creo un BufferedReader, que es NewBufferedReader, y le paso como parámetro este FileReader. Aquí se podría pasar un file. A este punto, puedo hacer una cosa de este estilo.
00:35:04
mientras
00:35:21
br.redline
00:35:22
esta cosa de aquí es un
00:35:24
es leer una
00:35:26
fila, una línea
00:35:28
de texto, ¿vale?
00:35:30
esto me lo guardas dentro de línea
00:35:32
y mientras que esta línea
00:35:34
no sea null
00:35:36
es decir, que he leído algo
00:35:37
me he ido al fichero, he leído
00:35:39
y la respuesta que me ha dado no ha sido null
00:35:42
¿vale? pues
00:35:44
imprimo esa cosa
00:35:46
en pantalla
00:35:48
aquí habrá errores, cosas por el estilo, etc
00:35:49
finalmente cuando he acabado de leer todas las cosas
00:35:55
y cuando llegará un momento en que esto explote o acabe con un null
00:35:58
pues entonces lo que hago aquí es cerrar el file reader
00:36:02
esto en el 95% de nuestros ejercicios no sirverá
00:36:07
porque nosotros leemos y acabamos el programa
00:36:14
Son micro ejercicios. En términos de un proyecto más grande, yo debería estar pendiente de cuando un fichero se ha leído y no me hace falta más y que entonces lo pueda cerrar, pueda cerrar el canal de comunicación con ese fichero.
00:36:18
porque si se me olvida
00:36:35
y yo tengo que abrir un millón de ficheros
00:36:37
y estos millones de ficheros me ocupan
00:36:39
cada uno un trocito de espacio
00:36:41
en mi RAM, pues llega un momento
00:36:43
que tengo memory slicks en el sentido
00:36:45
de objetos que no me sirven
00:36:47
de nada, que se podrían quitar
00:36:49
pero no he quitado recursos
00:36:51
que se quedan allí ocupando espacio
00:36:53
porque en cada ejecución yo
00:36:55
creo un file reader y no lo
00:36:57
cierro y por lo tanto
00:36:59
él asume que antes o después
00:37:01
lo vas a reutilizar, entonces
00:37:03
se me queda ahí abierto, vale, entonces acostumbraos
00:37:05
a hacerlo, vale, si no, no, existe también
00:37:09
una versión del try catch que es el try con recursos en el que aquí
00:37:13
entre paréntesis declaráis unos
00:37:17
recursos que vais a utilizar aquí dentro, como por ejemplo estos dos
00:37:21
vale, y él en automático cuando acaba el block que trae
00:37:24
los destruye y hace un close de esa cosa aquí, vale
00:37:29
hoy en día se suele utilizar
00:37:33
no me interesa particularmente
00:37:35
pero lo veréis en códigos
00:37:37
y cuando luego programaréis
00:37:38
ahí afuera, posiblemente lo tendréis que utilizar
00:37:41
escritura de un archivo de texto
00:37:43
en vez de file reader uso file writer
00:37:48
en vez de baffered reader
00:37:51
uso print writer
00:37:53
print writer
00:37:55
a lo mejor os podría sonar
00:37:57
de algo
00:37:59
vuestro System.out
00:38:00
es un objeto PrintWriter
00:38:07
¿sí?
00:38:09
entonces los métodos que se encuentran
00:38:12
aquí, como por ejemplo PrintLn
00:38:14
son los que se utilizan
00:38:16
nosotros desde el primer día
00:38:18
literalmente que hemos programado
00:38:20
cuando hemos hecho System.out
00:38:22
PrintLn, System.out lo que es
00:38:24
es un objeto de tipo
00:38:26
PrintWriter, PrintLn
00:38:28
es un método de PrintWriter que me escribe
00:38:30
la string que yo
00:38:32
quiero y al final le pone un retorno de carro vale entonces el file writer
00:38:34
igualmente new file writer con la ruta del archivo para crear la cosa aquí un
00:38:41
poquito ahora os explico que quiere decir esto vale luego el print writer es un
00:38:47
nuevo print writer que sostanzialmente pilla este file writer como base el file
00:38:51
writer será el que escribe realmente el print writer es el que añade algunas
00:38:56
funcionalidades como escribir una línea eso quiere decir que escribo lo que
00:39:00
Entonces, por ejemplo, aquí lo que hace es que por 10 líneas lo que hace es escribir línea 1, línea 2, línea 3, línea 4 en un fichero, ¿vale?
00:39:03
Si explota algo, pilla la excepción, finalmente acaba, ¿vale?
00:39:14
Ten en cuenta que cuando creáis esto, el FileWriter está pensado para que tú abras un fichero y lo borres enteros y lo escribas desde el principio, ¿sí?
00:39:20
Si tú ya tienes un fichero y quieres añadir, pegar detrás cosas a ese fichero, tienes que ponerle true, lo que sea, coma true, ¿vale? Este es un parámetro que te dice, que normalmente es a false, ¿vale?
00:39:33
Que te dice si tú lo que quieres hacer
00:39:53
Cuando escribes es
00:39:55
Escribir desde el principio un nuevo fichero
00:39:56
Hasta si este ya existe
00:39:59
Borrar lo que estaba dentro
00:40:01
Y quedarte con lo nuevo
00:40:03
O si quieres hacer la operación de append
00:40:04
O sea
00:40:07
Lo que estaba, estaba
00:40:08
Y append detrás
00:40:10
Las cosas nuevas
00:40:12
¿Dudas?
00:40:13
Entonces, escritura de un archivo binario
00:40:18
Vale
00:40:20
aquí usa BufferedReader igualmente pero luego no lo debería utilizar BossWrite
00:40:21
lo escribe
00:40:29
este es un FileInputStream, BufferedInputStream
00:40:30
FileOutputStream y BufferedOutputStream
00:40:37
lo que hace es utilizar Arrays
00:40:41
entonces crea un Array de 1000 posiciones
00:40:44
hace bis.read de Array
00:40:47
este de aquí, vis.read
00:40:50
lo que hace es, te paso
00:40:52
un array, y yo
00:40:54
intento leer desde el fichero
00:40:56
hasta que el array
00:40:58
esté lleno, si hay
00:41:00
al menos 1000 bytes, leeré
00:41:02
1000 bytes de golpe, y ahora
00:41:04
tú tienes 1000 bytes, ¿por qué 1000?
00:41:06
porque aquí he puesto 1000, si pusiera 100
00:41:08
pusiera 100, ¿sí?
00:41:10
si leo menos, porque
00:41:12
en el fichero no hay 1000 bytes, hay solo 7
00:41:14
bytes, pues yo te devuelvo
00:41:16
cuántos bytes he leído, si alcanzo el final del fichero
00:41:19
antes de haber rellenado estos 1000 bytes
00:41:23
te rellenaré solo los bytes que podía, los primeros 7 bytes
00:41:26
por ejemplo, pero aquí te devuelvo cuántos he leído
00:41:31
con esto, yo puedo decir que mientras leída es mayor que 0
00:41:34
lo que hago es, esto quiere decir que he leído algo, porque si hubiese
00:41:38
0, quiere decir que no he leído nada, vale
00:41:43
Y lo que hace él es
00:41:46
Boss.write
00:41:49
Array, o sea, escribe este array
00:41:50
A partir desde la posición 0
00:41:53
Hasta la posición leído
00:41:56
Entonces si he leído 1000
00:41:58
Sería desde 0 hasta 1000
00:41:59
Si he leído 7, desde 0 hasta 7
00:42:01
¿Sí?
00:42:03
Y leídos es igual a
00:42:07
Biz.readArray
00:42:08
Esto lo leo otra vez
00:42:10
No sé por qué
00:42:12
Ah, sí, porque se prepara para la siguiente
00:42:13
vuelta de cosas. Hasta que no lea
00:42:15
nada. A ese punto, cierra
00:42:17
los dos. ¿Qué hace esta cosa aquí?
00:42:19
Y, no.
00:42:27
No hay ningún... Existe un punto, punto, punto,
00:42:32
escribirlo en otro fichero. Este es
00:42:34
copiar un fichero. Lo dice aquí.
00:42:36
Copia de un fichero.
00:42:38
Si os fijáis,
00:42:41
tiene un origen,
00:42:42
tiene una copia,
00:42:45
¿vale? Y lo que hace es
00:42:47
leer de mil en mil
00:42:48
los bytes de un fichero
00:42:50
y escribirlos en otro fichero.
00:42:52
Leo mil, escribo mil.
00:42:55
Leo mil, escribo mil.
00:42:56
Leo siete, escribo siete, acabado.
00:42:57
Hasta que no lea nada,
00:43:01
leo cero, y entonces ya está.
00:43:03
Esto es una copia a bajo nivel.
00:43:08
Estamos trabajando con arrays.
00:43:12
¿Qué es esto? ¿Un fichero de texto?
00:43:14
Me vale, me funciona.
00:43:15
¿Es un exe? Me vale, me funciona.
00:43:17
¿Es un dat? Me vale, me funciona.
00:43:20
¿Es un word? Me vale, me funciona.
00:43:23
qué estructura dinámica no sé qué me estás diciendo en fichero donde donde quieres usar
00:43:30
no esto es a byte porque la read no te pilla una rey list te pilla una rey en la en la bright no
00:43:46
te pilla una rey list te pilla una rey entonces esta es la versión básica de la cosa y no hay
00:43:58
hay una versión de la braille que te pille es ahí la puedes hacer si tú puedes crearte tu propio
00:44:06
my input stream my output stream que lo que hace es pillar de un array list pero debajo lo que hará
00:44:12
es crearte una reunión file input stream y utilizar a los arrays pero luego una vez que tú lo has
00:44:19
implementado tú desde fuera la utilizarás con lo que quieras si dudas y hasta aquí hemos llegado
00:44:24
- Materias:
- Programación
- Niveles educativos:
- ▼ Mostrar / ocultar niveles
- Formación Profesional
- Ciclo formativo de grado superior
- Primer Curso
- Autor/es:
- Stefano Chiesa
- Subido por:
- Stefano C.
- Licencia:
- Reconocimiento - No comercial
- Visualizaciones:
- 15
- Fecha:
- 27 de marzo de 2025 - 14:06
- Visibilidad:
- Clave
- Centro:
- IES ROSA CHACEL
- Duración:
- 44′ 36″
- Relación de aspecto:
- 16:10 El estándar usado por los portátiles de 15,4" y algunos otros, es ancho como el 16:9.
- Resolución:
- 1152x720 píxeles
- Tamaño:
- 107.87 MBytes