Saltar navegación

2025-05-05-Programacion - Contenido educativo

Ajuste de pantalla

El ajuste de pantalla se aprecia al ver el vídeo en pantalla completa. Elige la presentación que más te guste:

Subido el 5 de mayo de 2025 por Jose Manuel M.

30 visualizaciones

Tema 10 - Repaso Flujos de datos

Descargar la transcripción

Vale, pues si no tenéis así ninguna duda en particular, de la que queréis que hablamos antes de arrancar, vamos a hacer un pequeño repaso sobre el tema 10. 00:00:02
Visteis, el otro día os dejé grabado, me habíais comentado una de las tareas, hice una pequeña grabación el miércoles y la dejé colgada junto al resto de vídeos, supongo que veríais el mensaje en el foro. 00:00:12
y bueno, el plan un poco es 00:00:22
ver el tema 10 hoy, hacer un repaso 00:00:25
de la teoría y como os decía 00:00:29
el tema 11 y el tema 12, interfaces gráficas 00:00:32
y bases de datos, aunque las vamos a ir abriendo en las fechas 00:00:34
que yo creo recordar que ya abríamos mañana 00:00:38
el último tema de bases de datos, en verdad nos quedan 00:00:41
dos semanas, la semana que viene es la última tutoría 00:00:44
bueno, de estos dos temas 00:00:46
como comentaba en el mensaje 00:00:49
en el foro, de cara al examen será 00:00:52
testimonial si preguntamos alguna cosita. No os digo que no 00:00:55
entre porque son contenidos del curso 00:00:58
pero será muy testimonial. Entonces si 00:01:01
andáis sobrados de tiempo, que supongo que no, echarle 00:01:04
un ojo y si no, centraros hasta colecciones 00:01:07
y un poquito también este tema y ya está 00:01:11
de cara a lo que es el examen y ya tendréis tiempo de ver 00:01:13
el resto de cosas porque además 00:01:16
el año que viene tenéis una asignatura 00:01:18
que es acceso a datos, que habla mucho de 00:01:21
cómo conectarse a base de datos y todo esto 00:01:24
es decir, hace un desarrollo más amplio de lo que trata 00:01:28
el tema que abriría mañana en principio 00:01:30
interfaces gráficas, pues la verdad 00:01:33
es que de escritorio, bueno ahí están las librerías 00:01:36
si permite utilizarlas, pero 00:01:40
el acceso a Java 00:01:42
o sea, el desarrollar ventanas en Java 00:01:44
no es lo más típico, entonces bueno 00:01:48
de todas formas sí que es interesante porque bueno pues 00:01:51
se aprende un poco, la semana que viene 00:01:53
pegamos un pequeño repaso, hacemos alguna cosita 00:01:57
se aprende un poco como puede ser la programación 00:01:59
dirigida a eventos, eventos bueno que se generan 00:02:03
en el momento en el que pinchamos por ejemplo en un botón con un ratón 00:02:06
o pasamos el ratón por encima de algún 00:02:09
control o minimizamos la pantalla 00:02:12
todas estas cosas, digamos que son eventos que se producen sobre la aplicación 00:02:15
se detectan y como consecuencia que se genera ese evento 00:02:18
nos permite ejecutar una zona de código 00:02:21
que es donde ponemos lo que queremos que pase 00:02:24
es decir, pinchamos un botón, pues se genera un evento 00:02:26
como consecuencia de ese evento 00:02:29
el flujo de ejecución del programa pasará a un determinado método 00:02:31
y en ese método hacemos lo que queremos que pase 00:02:36
si ha sido pulsar un botón que es salvar una información en una base de datos 00:02:38
pues ahí codificaremos el guardar esos datos en la base 00:02:42
de datos o lo que corresponda según el enunciado 00:02:46
pero bueno, eso es la semana que viene, en esta semana vamos a hablar 00:02:49
de los flujos, que es lo que tenemos en el tema 10 00:02:53
y mirad aquí, en el tema 10 00:02:57
vamos a ir como siempre apoyándonos 00:03:02
en el código con el entorno de desarrollo, no sé si entiendo que habréis tenido 00:03:06
la oportunidad de leerlo. Y bueno, aquí hay un esquema que puede ser bastante interesante 00:03:10
para ponernos un poco en situación. Por clasificar un poco lo que son los flujos. 00:03:15
Los flujos de comunicación es la vía, yo siempre lo comento como si fuera una tubería 00:03:21
que conecta nuestro programa con el exterior. En un extremo está conectada esa tubería 00:03:29
a nuestro programa, como os digo, y en el otro extremo, pues 00:03:35
a la fuente con la que nos estamos comunicando. Podemos tener flujos 00:03:39
que sean de entrada, es decir, para capturar información en nuestro programa 00:03:43
y flujos que sean de salida, para ser capaz de transmitir información 00:03:47
desde nuestro programa al exterior. Y estos flujos 00:03:51
pues la fuente con la que nos comunicamos desde el programa 00:03:55
pues puede ser teclado, pues sería un flujo de entrada 00:03:59
el System.in este que venimos encasulando todo el tiempo en la clase Scanner, pues es un flujo de entrada en particular para ubicarlo dentro de todo este esquema, sería un InputStream, es como está codificado el System.in, como está adaptado, podría ser la salida estándar a pantalla, 00:04:04
o bien la salida de errores del programa que nos lo saca a consola, a pantalla 00:04:28
eso sería un flujo de programa, comunica nuestro código con el exterior 00:04:32
en este caso con la pantalla, que yo creo que es un print stream 00:04:36
como está implementado, pues fijaros si venimos por aquí por la zona del output stream 00:04:40
tenemos aquí el print stream, pues cuando hacemos un system out 00:04:44
el system out está 00:04:48
encasulado dentro de un print stream, con lo cual los println estos que ponemos 00:04:51
están desarrollados en esta clase, en la librería de Java. 00:04:56
Más flujos con los que comunicamos nuestro programa, pues es con los ficheros. 00:05:02
Tenemos ficheros en disco que podemos querer leer desde el programa o escribir, 00:05:07
que es donde se centra principalmente este tema. 00:05:11
Entonces tenemos clases que nos facilitan el manejo de la lectura de ficheros 00:05:16
o de escritura de ficheros. 00:05:21
Entonces, por ejemplo, por aquí tenemos FileInputStream, ¿veis? Para leer, ahora hablamos de lo que significa stream y no significa, pero bueno, aquí tenemos que empieza esta clase con el nombre file, pues para leer desde ficheros o para escribir en ellos, pues tenemos la opción de FileOutputStream. 00:05:22
por aquí tenemos otra que es FileWriter 00:05:41
me parece, mirad, aquí tenemos FileWriter 00:05:47
luego, no son estas las únicas vías por las que 00:05:50
podemos comunicar nuestro programa con el exterior, a través de pantalla 00:05:55
o teclado, o a través de ficheros, otro mecanismo 00:05:58
podría ser, aunque esto quizás no estaría tanto enfocado a los 00:06:03
flujos de datos, podría ser a través de bases de datos, como el último tema 00:06:07
o el año que viene que lo veréis en desarrollo de interfaces, como os comentaba antes. 00:06:11
Y luego es típico en el mundo actual que abramos el navegador y nos conectemos a un servidor web 00:06:17
o hagamos una consulta a un servidor DNS, una transferencia de ficheros a través de servidores FTP. 00:06:23
Pues estas comunicaciones entre dos aplicaciones, una la que es la servidora y otra la que es la cliente, 00:06:32
Sería el servidor web, por ejemplo, de marca, que lo tiene en sus instalaciones marca, tendría un servidor web en un ordenador, servidor, y nosotros nos conectaríamos con un cliente que sería nuestro navegador, pues para que se establezca esta comunicación entre el navegador y el servidor web, se genera un flujo de datos también que comunica estas dos aplicaciones, que eso sería un socket. 00:06:38
Y esto lo veréis el año que viene en la asignatura de programación de servicios y procesos. 00:07:01
Pero una vez más estaríamos comunicando dos aplicaciones, una de ellas podría estar desarrollada en Java y la otra no, o las dos en Java o ninguna en Java podría ser. 00:07:08
Entonces en Java, pensando en Java, pues también se generaría un flujo de comunicación que pone en contacto nuestra aplicación con una fuente externa de la cual recibimos la página web del servidor marca, por ejemplo, si estamos haciendo las veces de cliente web para recoger los datos. 00:07:20
Esto para situarnos y aterrizar en el concepto flujo de datos, comunicar nuestra aplicación con el exterior y a la hora de organizarlos, seguimos un poco también analizándolo aquí en este esquema, tenemos dos alternativas. 00:07:40
Por un lado, los que tienen que ver con stream, que tenemos aquí input lectura de streams y por aquí output salida de streams. 00:07:55
Y luego tenemos otro bloque que son los que tenemos por aquí abajo, que sería el reader, este reader sería el equivalente, digamos, a este nivel del input stream y el writer sería el equivalente del output stream. 00:08:06
¿En qué se diferencia InputStream, OutputStream de Reader y Writer? 00:08:20
Mira, cuando estamos hablando de streams, tanto para el Input como para el Output, 00:08:26
se considera que el intercambio que se realiza a través del flujo, 00:08:32
bien sea con cualquiera de todos los posibles flujos de los que hemos hablado antes, 00:08:35
se hace byte a byte, es decir, se cogen grupos de 8 bits y se transfieren a través del flujo. 00:08:40
Si estamos leyendo un fichero, pues leemos 8 bits, nos da igual lo que sea. Si estamos escribiendo, pues escribimos 8 bits, nos da igual lo que sea. 00:08:48
Que estamos comunicando una aplicación con otra a través de un socket, enviamos 8 bits y el otro lee 8 bits. 00:08:57
Digamos que sin preocuparnos el uso que luego dentro de la aplicación está teniendo esa información. 00:09:04
Vale, pues esto es lo que sucede con los streams 00:09:10
Si damos un pasito más allá, resulta que puede ser que a estos bits 00:09:19
Bueno, imaginaos por ejemplo en este caso de streams 00:09:25
Un caso en el que no tendríamos que ir mucho más allá 00:09:27
Pues pensad que lo que estamos cogiendo es una imagen 00:09:31
Entonces tenemos un ficherito JPG con una imagen 00:09:34
que no está construido a base de palabras 00:09:38
o de textos, sino que directamente los píxeles luego 00:09:42
van a ir cogiendo colores y tonos en esos colores 00:09:45
en base a la información que tenga bit a bit cada uno de los datos que van 00:09:49
llegando. Se irán agrupando luego para esto. Si vamos a transmitir una 00:09:54
imagen de un ordenador a otro, podríamos hacerla directamente a través 00:09:57
de un stream. Pero puede ser que esa información 00:10:02
la queremos guardar en ficheros que estén, digamos, codificados a nivel de carácter. 00:10:05
Muy habitual que guardemos un fichero con información, pues no sé, una carta que queremos escribir. 00:10:11
Hola amigo, ¿cómo estás? Espero que hayas pasado un buen puente, nos vemos en unos días. 00:10:16
Pues esta información es verdad que la podemos guardar byte a byte, 00:10:23
porque no dejan de ser conjuntos de bits cada una de las letras, 00:10:27
pero igual queremos guardarlo, digamos, dando un salto 00:10:30
conceptual más alto y haciendo una encapsulación de esos bits para que 00:10:34
tengan ya un cierto tratamiento como caracteres, es decir, le damos cierto 00:10:38
sentido ya a los bits para que luego sea más fácil su trabajo 00:10:42
entonces eso, en lugar de hacerlo con streams, lo hacemos 00:10:46
a través de estas otras clases, que ya en lugar de guardar byte 00:10:50
a byte como agrupaciones de 8 bits, ya guardan 16 00:10:54
bits y lo guardan en formato de carácter y con estos hacemos lectura ya en formato de carácter 00:10:58
y con los writers enviamos o guardamos en un fichero información a nivel de carácter. Ahora 00:11:05
vemos también cómo vamos trabajando con ello. Entonces, primer concepto, flujos. Segundo 00:11:11
concepto, diferenciar entre streams y los que tienen este otro criterio ya de carácter, 00:11:17
Es decir, le damos cierto sentido a esos datos que se están transmitiendo por los flujos. Y luego hay otro concepto, bueno aquí hay muchas clases que no vamos a ver todas, vamos a trabajar sobre algunas de ellas, pero otro concepto que también es interesante es el de Buffered. 00:11:25
Fijaros, por aquí tenemos un BufferedInputStream, por aquí tenemos un BufferedOutputStream y por aquí debemos tener un Buffered, algún otro Buffered también. 00:11:42
Aquí, BufferedReader, por aquí, estaba buscando este tercero. 00:12:00
¿Qué sucede cuando hacemos accesos con clases que no manejan el Buffer? 00:12:03
Pues se entiende que cada una de las lecturas o escriteras que hagamos, por ejemplo, en un fichero, 00:12:10
que es uno de los modelos de flujos de datos, se hace, si es un string byte a byte, 00:12:15
entonces cada vez que hagamos una lectura se irá al disco, 00:12:22
imaginaos que ese fichero está en un pendrive, se irá al disco, cogerá ese byte y nos lo dará. 00:12:25
Si hacemos una segunda lectura en nuestro programa que tenemos un bucle de lectura de byte a byte, 00:12:30
pues se volverá a ir al disco y lo leerá. 00:12:34
Una tercera se irá al disco y lo leerá. 00:12:37
Y para la escritura igual, pues uno a uno irá haciendo escrituras en disco. Los accesos a disco en principio, bueno, pues es algo que para la eficiencia de los programas es razonablemente costoso para los programas. 00:12:40
Entonces si buscamos eficiencia lo que podemos hacer es utilizar clases que trabajan con buffers. Estos buffers son espacios de memoria intermedia, normalmente a nivel de hardware se almacenan en trocitos de RAM, en los cuales cuando hacemos el acceso a disco para lectura se trae mucha información de un golpe, con lo cual los accesos a disco son menos costosos y los agrupan todos en memoria RAM. 00:12:54
Y ya el programa, en lugar de irse al disco, leerá desde memoria RAM esos datos, con lo cual se gana eficiencia al tener los buffers y además se facilita la posibilidad de leer grupos de datos a la hora de coger los orders del buffer y no estarlos cogiendo desde el disco. 00:13:20
entonces imaginaos que queremos hacer una lectura de información con un determinado formato 00:13:40
y que tenga ese formato ya esté basado en caracteres 00:13:51
pues que podríamos hacer, podríamos perfectamente iniciar la conexión a través de un input stream 00:13:56
vamos a hacer una conexión a un fichero como para recoger bytes 00:14:03
pero en lugar de manejarlos en el programa como stream 00:14:10
este inputStream podemos venirnos por aquí 00:14:13
por ejemplo encasularlo en un inputStreamReader 00:14:15
que lo que hace es convertir un stream a un reader 00:14:19
es decir, le da ese cierto formato a carácter 00:14:22
y luego este inputStreamReader podríamos decir que 00:14:24
lo vamos a terminar en realidad desde la aplicación 00:14:28
leyéndolo con un buffer a reader 00:14:30
es decir, le vamos metiendo diferentes capas 00:14:32
y desde el programa podemos leer a nivel de carácter 00:14:35
desde un buffer habiendo hecho toda esta conversión de información ahora lo vamos 00:14:39
viendo en los programas entonces vamos mirar vamos a irnos al código y empezamos a hacer 00:14:46
cosas ya de todo esto una vez hecha esta pequeña introducción unimos eclipse por aquí se lo piensa 00:14:51
un poquito vamos a crear un proyecto quería elegir todo algo más se me ha quedado en el 00:15:35
nombre del proyecto tema 10 vamos a crear el método de inicio mira lo primero que vamos a 00:16:03
hacer si os parece para empezar a trabajar es pensando en input string lectura de carácter 00:16:49
a carácter el primer flujo que tenemos que funciona ya bajo este modelo es el system 00:16:56
in que ya lo conocemos de haber trabajado con él otras veces para leer información desde teclado 00:17:03
entonces fijaros podríamos y decir si ponemos aquí system acordaros que normalmente ahora 00:17:10
después lo hacemos también. System.in lo que hacíamos era con Scanner, 00:17:16
creábamos un objeto de la clase Scanner y en el constructor de la clase Scanner 00:17:21
decíamos que en casule, es decir, le ponga una capa como si fuese una cebolla 00:17:25
y el System.in fuera el corazón de la cebolla, le poníamos una capa por encima 00:17:29
de otra clase que tenemos definida en las librerías de Java que es la clase Scanner. 00:17:33
¿Qué pasa con la clase Scanner? Pues que permite trabajar a nivel de carácter 00:17:39
y además con información metida 00:17:43
como en buffers, como decíamos, como las buffers 00:17:46
de las que hemos hablado antes. 00:17:49
Para nuestra comodidad en el programa, encasulábamos 00:17:52
el SystemIn dentro de Scanner, ahora después lo hacemos 00:17:55
nuevamente, pero SystemIn ya de hecho 00:17:57
realiza una conexión de un flujo 00:18:01
pero bajo el modelo de InputStream. 00:18:05
Entonces si cogemos y decimos 00:18:09
SystemIn.SystemIn 00:18:10
punto en punto fijaros como ya nos ofrece realmente existen cosas que hacer y una de 00:18:19
las cosas que tenemos es aquí un rit pues esto lo que nos están haciendo es una lectura de 00:18:25
información a través de un flujo byte a byte y fijaros que nos permite hacer una lectura que 00:18:32
nos devuelve un entero vale un entero que cogerá la información de un byte o incluso podemos indicar 00:18:40
aquí que tenga como parámetro 00:18:47
un array de bytes, vamos a hacer las dos cosas 00:18:51
decimos int y valor, definimos una 00:18:54
variable por aquí, system int a quien está asociado, recordad que 00:19:02
es el flujo de datos que tenemos asociado a la lectura de teclado 00:19:08
y como es un input string 00:19:12
ofrece el método read, nos dice que lo metamos dentro de un try catch 00:19:15
para capturar excepciones de errores que se puedan producir 00:19:26
y ahora si hacemos aquí un system.out.println 00:19:29
tened en cuenta que aquí, system.out 00:19:35
es otro flujo de datos, según estamos hablando, en este caso 00:19:40
comunica nuestro programa con formato de salida hacia la pantalla 00:19:43
salida estándar, la pantalla, y system.out 00:19:49
si system.in está basado en 00:19:52
un InputStream, si está en Auth, está basado en un PrintStream 00:19:56
que tendrá, es una clase que está ahí en Java, fijaros esta 00:20:00
jerarquía de clases, de la clase Auth, está la clase 00:20:05
InputStream, que es una clase abstracta, de la cual 00:20:09
o es una interfaz, no sé, muy bien, qué significa esto 00:20:12
y por aquí tenemos otras clases que van heredando de estas anteriores 00:20:17
Pues OutputStream es un PrintStream, también es un flujo de datos 00:20:21
una forma de gestionar flujos de datos 00:20:26
Ese flujo de datos tiene un método implementado que es el println, entonces si aquí ponemos que nos muestre y valor, vamos a poner aquí un system.out.println, volvemos a utilizar ese flujo de datos, dime un carácter, entonces si ejecutamos por aquí, me dice que lo mantenga inicializado aunque lo vamos a sobreescribir aquí el valor, 00:20:29
dice, dime un carácter, digo una D 00:21:20
y fijaros, me muestra un 100, 100 que es, pues es un valor 00:21:24
de un entero, es un byte, si aquí le hacemos un casting a un char 00:21:28
a ver, ese es el valor ASCII de la D que he puesto en este 00:21:33
momento, si yo cojo y digo aquí D, ahora ya me dice D, porque 00:21:38
del valor 100 he hecho un casting y me lo ha convertido a un char 00:21:42
si no, pues directamente me muestra el valor de 00:21:44
sin preocuparse de formato ni nada el valor de un byte 00:21:48
un byte que está guardado en este caso en un entero, pues es lo que me muestra 00:21:53
con el 100, voy a poner los dos, veis, D 00:21:57
el 100, aquí me muestra este 100 y este D, si yo hago una ejecución y pongo 00:22:07
D A, en realidad aquí se va a quedar un poco bloqueado 00:22:12
el input hasta que le meta un enter, pero si le doy un enter 00:22:16
fijaros como lo que me muestra es un único carácter, este la D 00:22:19
el de la A no me ha mostrado nada 00:22:23
si yo pongo 00:22:25
dos ahora y ejecuto 00:22:26
dos, pues si pongo 00:22:33
de A, pues me leerá el primero 00:22:35
con el 100, bueno me ha mostrado 00:22:37
dos veces porque no he vuelto a hacer lectura 00:22:41
voy a meterlo aquí 00:22:43
dentro del try catch 00:22:49
sí, pero como 00:22:51
el método read 00:23:01
lee un solo byte, pues no ha leído más 00:23:03
ahora hacemos que lea 00:23:05
todos los que haya 00:23:07
en este caso lo que ha pasado es que había hecho un solo read 00:23:08
pues entonces ha leído un byte, este método lee un byte 00:23:11
y el primer byte era la D, pues ya está, esto es lo que ha leído 00:23:16
la A, bueno pues si hacemos una segunda lectura del system in read 00:23:19
pues leerá la A, mirad ahora he puesto dos read aquí 00:23:24
cogemos, a ver, lo salvo por aquí 00:23:28
si pongo D A, pues ahora ya me dice 00:23:32
he leído el primero con un 100 y el segundo con un 97, que después de hacer el casting me dice que es una D y que es una A. 00:23:38
Aquí, si no recuerdo mal, existe el método SystemInAvailable que indica mientras haya información disponible para lectura. 00:23:48
Entonces aquí podríamos poner while mientras haya información disponible para la lectura. Bueno, pues hazme, mientras haya información para la lectura, a ver aquí qué es lo que le pasa. Vale, a bailable. Esto debe devolver, a ver, ¿qué devuelve? 00:23:58
no debo devolver un boolean 00:24:29
y por eso se me queja, mira devuelve un entero 00:24:34
entonces 00:24:38
para que poderlo meter dentro de un while o dentro de un if habrá que decir 00:24:41
algo así que se evalúe, vamos a probar 00:24:46
entonces ahora cogemos y decimos da 00:24:49
aquí, o menos uno, puede ser 00:24:53
puede ser así. Bueno, pues aquí lo tenéis como, bueno, con el menos uno validando el final del 00:25:00
flujo, pues nos lee tantos caracteres, pero fijaros que estará en el bucle tantas veces como caracteres 00:25:29
haya si utilizamos el método read. También el system.in nos permite leer un array. Vamos a hacerlo 00:25:36
con un array. Decimos, ¿un array de qué? Pues fijaros que es un stream, es un input stream, entonces es 00:25:43
un array de bytes. De hecho, en lugar de int, aquí podríamos poner, yo creo, byte. Vamos a ver si nos 00:25:51
deja byteR. Vamos a hacer una lectura de un array. Vamos a darle un tamaño. Yo creo que si no, no va a 00:26:00
fallar. Aunque no utilicemos luego todo el array para los caracteres que le damos. Vamos a darle, 00:26:28
por ejemplo, un tamaño de 20. Y ahora podríamos poner aquí system.inread. Y en lugar de utilizar 00:26:35
este método que nos devolvió un entero, vamos a utilizar este otro 00:26:47
que lo que lee se lo guarda en el array que pongamos aquí 00:26:51
y aquí lo que nos devuelve es el número de caracteres que se han leído 00:26:55
entonces hacemos aquí un read, indicamos que queremos que guarde la información 00:26:59
en varray y aquí podemos poner un int 00:27:03
y num 00:27:10
num vice leídos, lo metemos en el try catch 00:27:13
entonces esto lo que se entiende es que para este array tenemos un espacio 00:27:27
de 20 ¿verdad? entonces no podríamos meter más de 20 bytes en la 00:27:33
lectura pero hasta 20 pues sí, con este system.ir este otro método 00:27:37
lo que hará será leer los que, los caracteres 00:27:42
que haya pendientes de leer, será algo parecido a este while en el cual leíamos 00:27:46
uno a uno, lo único que leerá todos de golpe, y ahora para recorrer 00:27:49
todos los arrays que tenga el byte 00:27:54
pues cogeríamos y haríamos un while 00:27:56
mientras, o un for 00:27:59
vamos a hacerlo con un for, for, mientras int 00:28:03
i sea igual a cero hasta que i 00:28:08
sea menor que el número de bytes leídos 00:28:11
hacemos un i++, y en cada uno de estos que estamos leyendo 00:28:15
pues lo podemos mostrar por pantalla, entonces la información la tenemos en el array 00:28:24
podemos hacer un system.auth.println 00:28:28
de la posición i 00:28:34
y si queréis podríamos hacer también esto mismo 00:28:38
pero haciéndole un casting a un char 00:28:44
para que se parezca al ejercicio que hacíamos antes 00:28:45
cuando leíamos de uno en uno 00:28:47
bueno, a este no le gusta esto 00:28:49
fijaros, el motivo es que este está definido 00:28:55
esta variable está definida dentro del ámbito del try 00:28:58
con lo cual es una variable local a este ámbito 00:29:02
y estamos intentando utilizarla aquí 00:29:04
dice no existe esta variable, pues lo que podemos hacer es definirla 00:29:06
aquí fuera y aquí usarla, entonces como ya ahora 00:29:10
ya está aquí, está definida en este ámbito, con lo cual está tanto disponible aquí 00:29:17
como aquí, y ahora por ejemplo metemos aquí abc 00:29:21
y fijaros como, bueno ponle los tres, el número de caracteres leídos 00:29:27
hace el for hasta tres veces, porque se habrá cargado aquí 00:29:32
porque hemos leído tres bytes y se trabaja con ello 00:29:36
fijaros que podemos perfectamente aunque sean caracteres leerlos como a raíz de bytes y luego 00:29:40
hacer las gestiones que vayan tocando para trabajar con ellos como caracteres vale podríamos 00:29:45
pero si queremos despreocuparnos de hacer esto porque sabemos que van a ser caracteres y queremos 00:29:50
ya que tenga ese formato que podemos hacer con el sistema pues mira fijaros podríamos y hacer 00:29:57
lo que venimos haciendo desde hace bastante tiempo para no trabajar con bytes con enteros 00:30:02
o con bytes, en realidad esta lectura está leyendo 00:30:08
byte a byte, aunque lo estamos metiendo en una variable numérica de mayor 00:30:12
espacio de memoria RAM, pero está haciendo la lectura con cada uno de los reads 00:30:16
o en este caso, leyendo cada uno de los bytes en un array 00:30:20
en lugar de trabajar con bytes, podemos querer trabajar directamente con 00:30:24
strings, entonces, ¿qué era lo que hacíamos? 00:30:28
con el system.in para que nos resultase más fácil, pues decíamos, es cierto que sabemos 00:30:32
que System.in es un flujo de datos tipo string, pero vamos a utilizar clases que tengamos en la 00:30:36
librería de Java que nos faciliten la vida para trabajar cuando estemos considerando lecturas 00:30:46
desde teclado que sean caracteres. Entonces, ¿qué hacíamos durante el curso? Nos hemos ido a la 00:30:52
clase Scanner, que la tenemos en las librerías de Java, 00:30:58
New, Scanner, y decíamos 00:31:02
a Scanner vamos a encasular 00:31:06
con un objeto de la clase Scanner que un inputString 00:31:10
que es la lectura de teclado. Ahora después también podremos 00:31:14
coger, y aquí en lugar de poner que el inputString sea la lectura de teclado, 00:31:18
podremos poner que sea un fichero. Después lo hacemos. 00:31:22
¿Y cómo trabajaremos? Pues trabajaremos con los métodos que tiene 00:31:25
Scanner a través de este objeto en su librería de definidas, en este caso 00:31:29
para leer un fichero, que es un inputString, un flujo de datos de entrada 00:31:33
al programa byte a byte, y en este caso un inputString que era 00:31:37
un flujo de bytes que tenemos de entrada al programa, pero desde 00:31:41
teclado. Es decir, Scanner puede encasular cualquier 00:31:45
flujo de entrada, cualquier inputString que tengamos 00:31:49
aquí, lo importamos, y bueno, aquí no voy a hacer 00:31:53
nada nuevo, y fijaros como aquí ya somos capaces de 00:31:57
hacer un myscan, punto, 00:32:03
y hacemos un net, un netline, con un netline que nos devuelve, nos devuelve 00:32:15
una stream, ¿verdad? Systeming devuelve streams, no, sabemos que 00:32:18
devuelve bytes, pero como lo hemos encasulado con 00:32:22
una variable tipo scanner, pues conseguimos hacer esa transformación, 00:32:25
nos resulta muy cómodo en el programa. 00:32:31
y aquí podemos mostrar la información. Ya está, fijaros 00:32:32
como directamente hemos cogido un string que en este programa trabajamos con 00:33:00
string directamente y aunque vamos a leer desde teclado, en lugar de coger las cosas 00:33:05
metiéndolo en un array de bytes y haciendo transformaciones, construyendo 00:33:09
un string a partir de cada uno de los caracteres 00:33:13
aquí con posibles bucles que vayamos 00:33:17
haciendo, que podríamos construirlo a partir de esto ciertamente, leyendo bytes 00:33:21
pues aquí eso mismo digamos que estará haciendo 00:33:25
Scanner por detrás por nosotros y nos dice 00:33:28
pues para que tu programa quede más clarito y tú lo entiendas mejor 00:33:31
y te cueste menos el hacer el desarrollo, tú haz un 00:33:34
Sline que te voy a devolver un String, aunque estemos leyendo desde 00:33:36
un flujo de datos de 00:33:39
caracteres. Bueno, Scanner lo conocemos 00:33:41
desde hace tiempo, pero ahora bueno ya le damos un poco 00:33:46
más sentido a este Sistening que poníamos 00:33:48
desde el principio, que decíamos es para leer desde el teclado 00:33:51
pero cómo funciona eso. Fijaros, si System.in es un InputStream, hemos visto que podemos leer directamente desde este, pero todos estos pueden trabajar como InputStreams en realidad. 00:33:54
Hay clases especializadas dependiendo de la naturaleza de cada uno de los flujos de datos de los que vayamos leyendo. Entonces, por ejemplo, tenemos el FileInputStream para leer como un InputStream, 00:34:12
pero desde un fichero, bueno pues tiene cierta especialidad, está de alguna forma un poco especializado con aparte de las clases que tenga el input stream de los métodos pues tendrá el file input stream propios que nos facilitarán la vida para esto, por ejemplo a lo mejor el constructor del objeto de file input stream, ahora después hacemos uno pues tendrá la posibilidad de indicar del fichero de la ruta donde está el fichero desde el que queremos leer. 00:34:23
este input string, pues podemos querer y trabajar con él en lugar de 00:34:49
haciendo lecturas de bytes, byte a byte, pues podemos querer trabajar 00:34:56
con él con cierto formato ya dado. Hemos visto 00:35:00
una posibilidad que tenemos para el system in, que es con la clase scanner 00:35:04
que queda fuera de esta parte de la estructura de clases 00:35:07
de Java, estará por ahí en otro sitio definida, pero dentro de esta 00:35:12
estructura podríamos ese input string, trabajarlo como un reader 00:35:16
que ya nos da cierto formato. Entonces, ¿cómo podemos convertir 00:35:20
un stream en algo que sea un reader? Pues si nos fijáis por aquí, 00:35:26
los nombres nos suelen dar ideas y tenemos esta que dice 00:35:30
input de entrada, conviérteme un stream a un reader, es decir, 00:35:34
da cierto formato ya a los caracteres. Entonces, nos venimos por aquí 00:35:38
y decimos, System.im es un input stream. En este programa, 00:35:44
en particular puede ser que en lugar de trabajar con byte me interese trabajar con caracteres 00:35:56
pues bueno, una forma típica de empezar a hacer esa conversión 00:36:00
es decir, ese input, el stream lo voy a convertir a un reader 00:36:04
entonces cojo por aquí y empiezo a encapsular esa información 00:36:08
igual que antes he encapsulado con scanner, pues ahora la digo aquí 00:36:12
input stream reader 00:36:15
y sr, vamos a llamarlo 00:36:21
de inputStreamReader igual a new 00:36:27
inputStreamReader 00:36:30
Estoy creando un objeto de esta clase 00:36:35
que es esta que tenemos aquí. Y a este 00:36:39
constructor, la idea que tiene esta clase 00:36:47
definida en la librería de Java es que un stream de entrada 00:36:51
lo convierte a un reader de entrada 00:36:57
Es decir, los bytes que tenemos desde el stream le va a dar cierto formato ya para leerlos de 16 en 16 bits y darle cierto formato de carácter. 00:37:01
Y le indicamos el stream que queremos convertir a reader en el constructor. 00:37:11
Entonces aquí podemos poner un input stream que, por ejemplo, podría ser el system. 00:37:15
Vamos a cargar las clases desde Java.io. 00:37:20
Y esto lo que hará será esa conversión leyendo desde este stream. 00:37:28
pero otra cosa que hemos dicho que nos puede resultar interesante 00:37:33
es trabajar con información 00:37:36
leída desde el dispositivo, en este caso desde el teclado 00:37:39
en un buffer, entonces tenemos 00:37:42
la posibilidad de cargarlo en un buffer reader, ahora ya tenemos 00:37:45
un reader y queremos meterle un buffer 00:37:48
fijaros que como salida, esto ya es 00:37:51
un reader porque hemos hecho esa conversión 00:37:59
y de hecho, fijaros como 00:38:01
me ofrece métodos para leer ya directamente 00:38:05
directamente desde este reader 00:38:08
podríamos leer ya, pero por darle 00:38:12
por poner otra capita más a esa cebolla 00:38:14
pues podríamos coger y decir voy a crear 00:38:18
un objeto de la clase buffer reader 00:38:20
que lo que hace es un reader 00:38:22
recordad que esto en sí es un reader 00:38:25
que hemos obtenido desde este stream 00:38:29
y le indicamos el reader 00:38:32
al cual le queremos aplicar un buffer. Y ahora aquí podemos 00:38:46
escoger y hacer lecturas, fijaros como 00:38:56
información ya de tipo string, igual que con el scanner hemos 00:39:00
hecho lecturas de Nestline, pues aquí 00:39:04
tenemos la posibilidad con el método read, nos da alternativas y entre ellas 00:39:08
tenemos la de leer directamente una línea, es igual que 00:39:12
este vendría a ser con otra clase de Java, el Nestline que 00:39:16
tenemos con un objeto de la clase Scanner, desde el buffer ARRIVE. println br.redline 00:39:20
Me pedirá un try-catch supongo. Vamos a poner un system.println aquí para pedir información. 00:39:46
Dime algo. En este caso fijaros, estamos, hemos hecho tres aproximaciones al system.in, leerlo 00:40:01
como un stream, leerlo como una cadena de caracteres con una clase que tenemos en la 00:40:14
librería de java que la clase escáner y ahora vamos a leerlo desde una que está 00:40:19
colgando esta estructura desde el stream hemos convertido en un reader con el 00:40:25
input stream reader y ahora con el buffer reader vamos a leerlo apoyándonos en un 00:40:29
buffer que hemos creado hacemos el read line y 00:40:34
finalmente bueno ser lo que leamos lo sacamos por pantalla dime algo hola 00:40:39
¿Cómo estás? Bueno, pues ha hecho ahí todo el proceso, ha hecho la lectura, el readline, lo ha mostrado por pantalla, aquí lo tenéis. ¿Alguna duda? ¿Se entiende? Bueno, pues vamos a seguir trabajando con los streams, pero vamos a ir ahora a ficheros. 00:40:54
acordaros que tenemos, en Eclipse estamos trabajando con el proyecto T 00:41:25
y los proyectos, si no habéis cambiado el Workspace, la zona de trabajo, 00:41:34
la máquina virtual que los pasé yo, vosotros donde lo tengáis, 00:41:40
pues se van creando los proyectos en el Workspace. 00:41:44
Fijaros, aquí tenemos un directorio por cada uno de todos estos, 00:41:54
en particular este proyecto lo hemos llamado T, 00:41:58
y este es el punto donde la ejecución 00:42:00
desde Java busca la información, digamos es el punto raíz 00:42:05
entonces si nosotros creamos aquí un fichero 00:42:09
Nano es un editor de textos como del tipo del Notepad 00:42:11
que suele estar incluido en distribuciones 00:42:17
Linux, vamos a poner 00:42:21
fichlet.txt, vamos a crear un fichero aquí que sea 00:42:23
fichero LED de lectura, vamos a poner aquí 00:42:28
un hola y nada, pues fijaros aquí lo tenemos 00:42:32
ls, ya existe el fichero fichero LED, lo he puesto 00:42:40
en el directorio RAID del proyecto 00:42:43
aquí está el directorio src y bin, pues tal que por aquí 00:42:47
y fijaros haciéndole en morg, que es un comando en linux, pues que te muestra 00:42:51
el contenido, efectivamente tiene el hola este que hemos puesto como contenido 00:42:59
cuando lo hemos editado, ahí está el fichero 00:43:03
bueno, pues podemos hacer un poco la misma jugada, pero ahora para leer 00:43:06
un ficherito, si queremos hacer la lectura 00:43:14
directamente como streams, pues aquí lo que vamos a hacer va a ser 00:43:18
venirnos a esta clase, bueno, pues que nos ayuda un poco a 00:43:22
hacer el tratamiento como stream de ficheros, la file input 00:43:25
stream, en lugar de leer de este flujo 00:43:30
que era el teclado, pues ahora vamos a leer de otro flujo. 00:43:41
Hemos dicho que los flujos son mecanismos que utilizamos para comunicar 00:43:45
nuestro programa con el exterior. Un mecanismo es lectura de teclado, 00:43:49
pues ahora vamos a utilizar otro que es lectura de ficheros. 00:43:53
Entonces es File, InputStream, 00:43:56
File, InputStream, vamos a llamarlo Fizz, y aquí en el constructor 00:43:59
podemos indicar el nombre del fichero que queremos 00:44:16
leer que era fitch led aquí pondríamos la ruta donde se encuentra el fichero como lo he creado 00:44:20
justo en la en la ruta donde está el directorio en el directorio del proyecto en eclipse eclipse 00:44:29
aquí donde empieza buscándolo si no habría que poner una ruta relativa absoluta para que terminara 00:44:37
localizando el fichero pues la importamos por aquí hago el new por aquí vale y ahora esto me dirá que 00:44:41
lo meta dentro un try catch por si no existiera el fichero poder capturar fijaros la excepción 00:44:56
que captura file no phone excepción vale pues ahora aquí que tengo pues tengo un acceso a un 00:45:01
flujo en este objeto que es en particular un fichero como puedo leerlo pues como un stream 00:45:08
pues pongo aquí fix.read y fijaros que me permite igual que hacíamos con el system in antes la 00:45:14
posibilidad de leer byte a byte esta información veis leerlo como enteros o releerlo como array 00:45:20
de bytes vamos a hacer una jugada como la de antes la única diferencia en el programa es que 00:45:27
ahora estamos indicando que el objeto fish es del tipo file input string y que lea de este 00:45:33
sistema a diferencia de lo que hacíamos antes que lo que hacíamos era leer antes leíamos desde 00:45:39
sistema ahora de fislet pero en realidad es un flujo conectado a mi programa en un lado de la 00:45:46
tubería de ese flujo está pinchado en mi programa y estoy leyendo la información como streams entonces 00:45:53
ahora voy a hacer una copia de estos dos estando variable la voy a poner por aquí y si hago que un 00:46:00
rito aquí ahora de este le digo que me lo cargue por aquí añado la cláusula cats que tiene a este 00:46:12
que tenga que ver con la lectura fijaros y o excepción y ahora aquí habré leído un carácter 00:46:28
si yo pongo aquí un system.out.println de y valor a una ejecución y me dice 104 104 que será 00:46:34
pues será el valor el valor así de probablemente de la h a ese valor como antes si le hago un 00:46:51
casting para decir oye no me muestres el valor numérico muéstrame convierte ese valor numérico 00:47:07
a un carácter, pues fijaros 00:47:12
como ahora ya me dice efectivamente que es la H 00:47:15
y si en lugar 00:47:17
de leerlo con read, como hemos 00:47:19
hecho aquí 00:47:21
estoy repitiendo un poco 00:47:21
los mismos pasos que habíamos hecho 00:47:24
en la lectura anterior 00:47:27
le paso un array de bytes 00:47:30
pues cargará aquí todos los bytes que tiene 00:47:32
la lectura y aquí el número de 00:47:34
bytes que 00:47:37
ha leído, que si es 00:47:38
o en principio deberían ser cuatro. 00:47:41
Hacemos aquí 00:47:44
System.out.println 00:47:45
byteleidos 00:47:49
y valor 00:47:58
y ahora voy a hacer copy-paste aquí 00:48:08
y así perdemos menos tiempo 00:48:11
del bucle este que había hecho aquí. 00:48:13
Aquí en lugar de inum byteleidos 00:48:24
que habíamos definido ahí abajo, lo hemos cargado 00:48:25
el número de bytes aquí. 00:48:27
Pues ahí lo tenemos. 00:48:30
Entonces aquí lo que nos mostrará será 00:48:31
cada uno de los caracteres, como lo hemos cargado en este caso 00:48:33
con el read de un stream en un array de bytes 00:48:37
pues nos mostrará uno a uno, nos mostrará la H, la O 00:48:41
la L y la A, que es el contenido que tiene el fichero 00:48:45
la H con su valor ASCII, ¿veis leídos? 00:48:48
5104, curioso 00:49:01
que me diga aquí 5104, no entiendo muy bien por qué 00:49:13
porque luego en verdad el bucle si que lo hace aquí 00:49:16
para los cuatro, bueno en cualquier caso ha leído la O 00:49:20
la H, la O, la L y la A, es decir la información que teníamos 00:49:25
en el fichero, por seguir dándole otra vuelta 00:49:28
a esto, sobre todo para que veáis 00:49:33
que bueno, que intentando 00:49:46
buscar simplificarlo, en realidad luego no resulta 00:49:50
muy complicado, esto 00:49:54
simplificando el concepto 00:49:56
vamos a coger el catch para que nos compile por aquí 00:49:59
del try 00:50:02
hacerlo así más rápido 00:50:03
que nos ayude Eclipse 00:50:12
vamos a meterlo con un try catch y listo 00:50:13
ya está, pues fijaros 00:50:17
esto, fizz que es 00:50:18
un stream 00:50:20
aquí podríamos coger y decir 00:50:21
voy a buscar el copy pega 00:50:24
podríamos decir, en lugar de trabajar con 00:50:28
un stream, esto en verdad va a estar basado 00:50:37
en caracteres, voy a utilizar un objeto 00:50:39
de la clase scanner, pero en lugar 00:50:41
de leer de system.in que era un stream 00:50:43
ahora voy a leer de esto 00:50:45
que es un string, aunque el otro lado de la, hay un lado de la tubería pinchado en mi programa, el otro lado está pinchado un fichero, no está pinchado al teclado, pues aquí se lo indicamos, veis, con el fichero del string, ahora que será, pues leerá, este dime algo ahora sobra, porque realmente no queremos que nos muestre esto por pantalla, esto lo ponemos como avisa nosotros mismos, porque tenemos que escribir algo por teclado, en este caso la lectura del 00:50:47
fichero la va a hacer directamente y como es un objeto de la clase escáner 00:51:20
que tiene disponible el nest line va a leer línea a línea con formato ya de 00:51:25
carácter con lo cual no va a poder devolver un string que mostramos por 00:51:30
pantalla y este objeto de escáner en realidad está pinchado un string y este 00:51:33
string resulta que ha resultado ser un fichero 00:51:37
entonces hacemos aquí una ejecución pero por aquí fijaros como me dice aquí un 00:51:41
hola, y si yo cojo 00:51:49
y vuelvo a editar el fichero 00:51:51
y pongo una primera línea con hola y una segunda con adiós 00:51:54
tiene ahora dos líneas, hola y adiós 00:51:58
hago una ejecución y me dice hola 00:52:01
¿por qué? porque he leído un next line 00:52:04
pero si yo ahora cojo aquí y hago 00:52:05
un segundo next line 00:52:09
pues me leerá dos líneas, una primera que dirá hola 00:52:16
y una segunda que dirá adiós. En cada una de estas líneas hemos hecho una lectura, ¿verdad? 00:52:21
Un next line, un segundo next line, método disponible en la clase scanner a través de este objeto 00:52:26
que está enchufado al fichero. Hemos leído dos líneas, pues nos han mostrado una línea y una segunda línea. 00:52:31
Por aquí lo tenéis. Mecanismo, pues el mismo que venimos haciendo todo el tiempo cuando hemos estado leyendo 00:52:39
system in lo único que ahora hemos trabajado con otra clase que tenemos por 00:52:45
aquí en lugar de con la clase del input string directamente con el que está 00:52:52
asociado él con el que está asociado él 00:52:56
la entrada información por teclado alguna preguntilla por ahí que si eso 00:53:01
ocurra una cosa interesante que ya os insistía que no estoy haciendo yo ahora 00:53:12
porque está acabando el programa 00:53:22
me refiero a que está acabando el programa porque acaba el main 00:53:24
que es interesante hacer 00:53:27
y que os lo comentaba ya también 00:53:28
para hacer siempre con escáner 00:53:30
es que vayáis cerrando los flujos 00:53:32
los flujos estos 00:53:35
pues tienen la posibilidad 00:53:37
del método que con escáner siempre 00:53:39
os he dicho, acordaros de cerrar 00:53:41
el flujo, aquí está definido 00:53:43
este nivel, fijaros como tienen 00:53:48
el método close, pues igual que el método 00:53:50
escáner, pues lo tenía también 00:53:52
pues para 00:53:54
para que se quede cerrado, si se acaba el programa 00:53:55
porque finaliza el main, en cualquier caso al acabar el programa 00:53:59
se va a cerrar, pero si el programa, imaginaos que se mantiene activo 00:54:04
continuamente, es un programa 24-7, si vais abriendo flujos y luego 00:54:08
ir cerrando, pues al final vamos estropeando un poco la memoria RAM 00:54:11
de hacer reserva de recursos 00:54:15
que no cerramos y bueno, pues siempre nos puede terminar dando algún problema 00:54:19
a ver más cosas por ahí que os puedo ir contando hemos estado todo el rato trabajando con input 00:54:24
stream pues mira vamos a ver ahora salida está trabajando un poco por este lado con el input 00:54:36
string con el file input string vamos un poquito ahora este lado el del output string y una de las 00:54:44
cosas que podemos hacer por ejemplo es escribir en un fichero con el con el file output string 00:54:50
si hacemos un file output string que escribiremos, escribiremos bytes 00:54:56
venga, vamos a ello 00:55:01
fijaros, estamos trabajando con string, vamos a escribir bytes 00:55:02
en este caso para salida, no como antes con para entrada 00:55:32
y hemos pensado trabajar con un fichero 00:55:36
es decir, la salida está enfocada a hacerla en un fichero 00:55:40
con lo cual el fichero sobre el que vamos a escribir, se lo podemos pasar 00:55:44
aquí como atributo, como parámetro. Vamos a poner File Feature Escritura. Se me queja porque no lo 00:55:48
tenemos importado, lo importamos de Java.io y ahora se me queja porque las gestiones con ficheros 00:56:01
siempre suelen estar gestionadas ante posibles excepciones, entonces le ponemos que le meta el 00:56:08
try-catch, file no fun excepción. Vale, pues 00:56:15
ahí tenemos un file output string, podríamos escribir 00:56:21
ya en este ficherito de salida directamente en base 00:56:24
a bytes, entonces si ponemos fold 00:56:29
write, por aquí lo tenemos, fijaros 00:56:31
que podemos escribir un array de bytes o un entero 00:56:38
bueno y alguna otra alternativa que hay más por ahí, vamos a poner aquí 00:56:42
valor valga 10 vamos a ponerlo que lo meta que añade la cláusula a este 00:56:49
track del lío excepción si hacemos una ejecución ahora este 00:57:02
programa fijaros como aquí hemos puesto directamente el nombre del fichero si 00:57:07
poner sin poner mayor mayor dato en la ruta sobre donde se va a escribir el 00:57:14
fichero con lo cual en principio se escribirá en la propia que tiene 00:57:19
definida por defecto el proyecto que es como hemos dicho aquí en verdad colgando 00:57:23
directamente del directorio del proyecto y decimos que escriba por ahí 00:57:28
normalmente los flujos como que intentan escribir primero en una zona de memoria 00:57:33
es intermedia en lugar de volcarlo a disco y luego lo vuelca a disco cuando 00:57:40
él le va apareciendo entonces si queremos hacer un volcado a disco 00:57:44
directamente solemos poner un flush que es lo que 00:57:47
haces todo lo que tengas pendiente de escribir, escríbelo a disco 00:57:51
y aquí podríamos poner si queremos un close 00:57:55
es decir, abrimos el fichero por aquí, al definirlo 00:57:59
con el constructor, escribimos, nos aseguramos que queda volcada la 00:58:03
información en disco y cerramos el flujo, hacemos aquí una ejecución 00:58:07
en realidad no hemos sacado nada por pantalla, el programa se nos ha 00:58:14
terminado, si nos ponemos aquí ahora, hacemos un ls, fijaros como nos ha 00:58:17
creado el ficherito este y si intentamos ver su información, fich de escritura, pues no se ve nada. 00:58:21
Vamos a probar con 100 y ahí se ve una D. ¿Qué sucedía? Que habíamos escrito un 10 que probablemente 00:58:37
era un carácter no visible, generaba, si te vas a la tabla ASCII, el valor 10 que habíamos intentado 00:58:49
escribir pues igual no es nada no es nada no es nada visible en el momento en el que lo edita 00:58:56
amor o el editor nano cambio de tiempo ya nos pone hay una vez qué sucede si volvemos a ejecutar este 00:59:02
programa es que volvemos a tener la de y si ponemos aquí un 101 ahora tenemos una es decir el valor de 00:59:11
valor del siguiente carácter que sucede que cada una de las ejecuciones nos está borrando la 00:59:28
información anterior e introduciendo la nueva. Antes había una D, ¿verdad? 00:59:35
Lo hemos vuelto a ejecutar con 101 y nos ha aparecido una E, pero la D 00:59:39
ha desaparecido. Si sobre un flujo de strings 00:59:43
queremos que en lugar de eliminar los datos anteriores 00:59:47
del fichero e incluir los nuevos, nos vaya añadiendo, 00:59:51
vaya haciendo un attach sobre la información anterior a la nueva, le podemos poner aquí 00:59:55
un segundo parámetro que sería un true, por defecto 00:59:59
que esto es añade, añade verdadero, si pones aquí false 01:00:03
elimina el fichero y si no pones nada 01:00:07
el valor por defecto es como false, entonces si ponemos aquí 01:00:11
un true, salvamos y hacemos una ejecución nueva 01:00:15
no venimos al fichero ahora, fijaros como ya tiene dos es, una de la anterior 01:00:19
y otra de la nueva, vamos a hacer una ejecución poniendo aquí un 0 01:00:24
y ahí tenemos la de, fijaros 01:00:27
que estamos escribiendo a través de enteros vamos a vamos a hacer una escritura a través de un array 01:00:39
ponemos aquí force right fijaros aquí nos ofrece la opción de meter un array de bytes en lugar de 01:00:47
escribir de esta forma pero seguimos escribiendo bytes para que esto tenga algo de información 01:01:00
Tendríamos que poner aquí un bear que en la posición 0 tenga un 100, que tenga un 101, en la posición 1, darle información al array. 01:01:06
Y si hacemos ahora una ejecución, ahora mismo el fichero tiene EED, ¿verdad? 01:01:30
Y vamos a ver si nos funciona. 01:01:34
Fijaros, el EED y la DEF, que son estos tres. 01:01:42
ha escrito directamente esa información, pero estamos escribiendo byte a byte 01:01:45
¿verdad? ¿por qué? porque es un stream, igual que con 01:01:49
el system.in antes que leíamos con un stream y éramos capaces de encapsular la información 01:01:53
pues tenemos la posibilidad de encapsular también datos 01:01:58
que vayamos a escribir en un ficherito 01:02:01
entonces del file output stream lo que podríamos 01:02:05
hacer aquí es mirar por aquí como podemos encapsularlo 01:02:12
Entonces el file output string que tenemos por aquí podemos decir, mira vamos a intentar encasularlo en, a ver, a ver, pues mirad una posibilidad, podría ser en un output string writer, writer nos escribe carácter a carácter y un string que es lo que tenemos en el file output string, un string lo convertimos en un writer, entonces tenemos un output de salida string writer. 01:02:16
y este writer, igual que hacíamos antes por seguir toda la jugada 01:02:46
este output stream writer, ya que tenemos de este de salida 01:02:53
un writer, podemos intentar hacerlo para escribir a través de un buffer 01:02:57
entonces podemos convertirlo en un buffer al reader, que es la misma jugada que hemos hecho antes 01:03:00
del input stream, que lo hemos convertido en un input stream reader 01:03:04
para lectura, y luego hemos utilizado un buffer al reader 01:03:08
pues ahora del output, del file output stream 01:03:12
podemos traernos ahora un outputStringWriter y ahora un bufferWriter 01:03:16
bueno, es jugar un poco con todas estas clases 01:03:21
y así nos evitamos tener que estar escribiendo byte a byte 01:03:25
si es lo que nos interesa, imaginaos que es una imagen 01:03:33
que estamos leyendo la de un fichero y pasando la otra 01:03:36
y queremos leerla byte a byte y escribirla byte a byte 01:03:39
pues ya está, leemos con un fileInputString 01:03:42
byte a byte y escribimos con un fileOutputString 01:03:46
byte a byte y tan a gusto 01:03:49
podríamos hacerlo así también, entonces este file output stream 01:03:51
hemos dicho que vamos a convertirlo en 01:03:58
a un writer, queremos que siga siendo de salida, con lo cual le decimos 01:04:01
output stream 01:04:06
writer, recibirá 01:04:09
un stream, verdad 01:04:28
este es un stream de salida, leído desde un fichero 01:04:30
fos, y queremos convertir ese stream 01:04:36
en un writer, los writers son de salida 01:04:42
siempre, pero bueno, es como se llama 01:04:46
entonces vamos a importarlo de yojaba, y ahora tenemos un writer 01:04:48
pero como nos interesa que ese writer trabajarlo como un buffer 01:04:53
para que tenga mejores eficiencias, ya ese writer directamente tendría 01:04:57
métodos para escribir, pero podemos todavía convertirlo en algo 01:05:01
que tenga buffer, que gestione un buffer 01:05:05
de memoria rampa a la hora de hacer las escrituras. 01:05:07
Entonces podemos coger aquí 01:05:11
y decir, este writer 01:05:12
que me lo convierta en algo que 01:05:28
se gestiona a través de buffer. 01:05:30
Y lo vamos a hacer 01:05:33
con un objeto de esa clase que es el 01:05:34
bw. 01:05:36
Hacemos tal que aquí, y ahora podemos hacer 01:05:38
aquí un bw.write 01:05:40
y este, fijaros como ya nos permite 01:05:47
escribir strings, cadenas de caracteres 01:05:50
completas. 01:05:52
hacemos ahí un flush, vamos a hacer una cosa 01:05:53
vamos a borrar el fichero y empezamos a escribirlo de nuevo 01:06:18
ya no existe el fichero de escritura 01:06:23
ejecutamos por aquí y hacemos ahora un more aquí 01:06:25
y fijaros como tiene ese hola como estás que hemos escrito por aquí con el write 01:06:31
si volvemos a ejecutar tenemos un hola como estás 01:06:37
y otro hola como estás, uno detrás de otro 01:06:44
fijaros que tenemos que vaya añadiendo 01:06:47
por aquí, a ver, si ponemos aquí un barra N 01:06:52
no tengo seguridad si el buffer greater nos va a meter una nueva línea 01:06:55
vamos a escribirlo dos veces con una nueva línea, mirad como ha metido una nueva 01:06:59
línea y en realidad este segundo también la ha metido y ahora 01:07:14
volvería a escribir aquí, con el barra N podemos meter una nueva línea igual que cuando hacemos 01:07:17
con el println, fijaros como va añadiendo todo el rato la información 01:07:22
¿por qué? porque tenemos aquí el attach este, si cogemos y hacemos así, fijaros 01:07:27
bueno, nos queda esto del último flush que hemos hecho 01:07:31
si hacemos otra nueva ejecución, a la hora de crear el fichero 01:07:41
entiendo que se habrá borrado lo anterior y tendremos nuevamente dos líneas solo, no se ha añadido 01:07:47
si ahora ponemos de nuevo el true aquí, para decir, oye 01:07:51
que vaya, mantenga la información anterior y añada la nueva 01:07:55
pues ahora ya tendríamos, entiendo, cuatro líneas, vamos a verlo, ahí lo tenéis 01:07:59
Vale, pues eso si lo metemos en un Buffer Writer, tenemos, fijaros, tenemos bastantes posibilidades, lo hemos hecho a través de un Buffer Writer, también tenemos aquí un File Writer, vamos a probar con el File Writer, al final todos terminan escribiendo en un fichero y un poquillo como la que os guste más utilizar. 01:08:03
vamos a probar un par de alternativas más 01:08:31
aquí lo que hemos hecho ha sido abrir como un stream 01:08:35
lo hemos convertido en un writer 01:08:45
y lo hemos metido en un buffer en el writer 01:08:46
pues otra posibilidad es 01:08:48
venirnos por aquí y decir mira voy a abrir el fichero 01:08:50
directamente como un file writer 01:08:53
no quiero stream 01:08:54
directamente esta clase ya 01:08:56
probablemente lo de abrirlo como un stream y hacer esa conversión 01:08:58
lo hará el constructor 01:09:01
de esta clase, probablemente 01:09:02
no sé claro, no he mirado el código pero probablemente 01:09:04
sea como lo haga, directamente abra como un stream 01:09:06
y ya todo este proceso que hemos hecho nosotros por pasos, lo hago ya aquí 01:09:09
pero si cogemos y hacemos un FileWriter, hacemos un new 01:09:13
le decimos el fichero que queremos abrir, y este pues nada 01:09:22
tiene la opción de FileWriter 01:09:43
método write 01:09:47
sí, por aquí write, fijaros, también write 01:09:50
hola de nuevo, hacemos un fw.close 01:09:54
borrarlo, el fichero de escritura este, y así que lo genere 01:10:06
de nuevo, le damos aquí a ejecutar, a ver que es lo que ha pasado aquí 01:10:18
se me ha quedado ahí colgado esa instrucción de los comentarios 01:10:27
de antes, vale, y ahí tenemos el Lula 01:10:37
de nuevo, pues también a través de esta otra clase que tenemos 01:10:45
en toda esta estructura por aquí, pues también lo podemos hacer, y luego 01:10:49
para terminar un poco de ver esto y pasar a contaros otras 01:10:53
cositas, ya por concluir vamos a algo que nos resulta también familiar, porque aquí estamos 01:10:57
utilizando el método write, el file writer, por aquí también hemos utilizado el write, que bueno, en 01:11:05
principio no parece que sean complicados, pero por irnos a algo mucho más familiar, que hemos dicho 01:11:14
que era el system out antes, pues el system out habíamos dicho que era un print writer, 01:11:19
es un PrintStream 01:11:26
yo pensaba que era un PrintWriter 01:11:36
tenía dudas si era un PrintStream o un PrintWriter 01:11:39
en cualquier caso el PrintWriter tiene 01:11:43
las opciones de métodos 01:11:45
que tenemos con el System.out 01:11:49
si definimos un objeto de la clase Print 01:11:51
también estará aquí, aquí lo tenemos 01:11:54
el print writer, este puede resultarnos cómodo porque si ponemos aquí 01:11:57
un pw ahora y hacemos un, intentamos 01:12:22
escribir, fijaros los métodos que tiene, el print, el print 01:12:26
ln, que estamos muy acostumbrados a trabajar con ellos 01:12:30
con el system out, entonces si definimos, aunque sea para escribir un fichero 01:12:34
con un print writer, pues aquí podemos poner 01:12:38
lo típico que ponemos de lo que queremos que nos salga por aquí en consola 01:12:42
con estos métodos en lugar de utilizar métodos nuevos 01:12:46
que nos podría costar más o igual nos acordamos menos 01:12:50
que los que trabajamos normalmente con él 01:12:53
porque los conocemos ya de System.out 01:12:56
vamos a hacer otra ejecución 01:12:58
ejecutamos por aquí, suponemos que hemos escrito 01:13:18
ejemplo con PrintWriter 01:13:30
entonces ponemos FitchX, ahí tenemos ejemplo con PrintWriter 01:13:33
hacemos una nueva ejecución 01:13:37
se mantiene lo mismo, yo creo que habrá borrado, veis, se ha borrado el anterior 01:13:39
y no recuerdo ahora mismo si este, admito también aquí un true, yo creo que sí 01:13:45
ah pues no, pues no, con print writer no te deja 01:13:49
añadir nueva información en un fichero, directamente 01:13:56
cuando haces un close, creas un objeto nuevo, ya no te deja hacer el attach 01:14:00
si utilizas el print writer directamente, si quieres hacer eso 01:14:04
pues te puedes ir por esta vía, hacerlo con un file output string 01:14:07
y luego ir encasulando la información. Otra cosilla que deciros 01:14:12
es que existe una clase que si no vemos hoy en la siguiente tutoría 01:14:18
la repasamos un poco, aunque sea rápido por dejar 01:14:22
tiempo en la siguiente tutoría también por si tenéis alguna duda que preguntarme 01:14:25
que es la clase File. La clase File permite 01:14:29
hacer diferentes cosas, ya os digo, si nos da tiempo hoy bien la vemos 01:14:34
y si no el próximo día. Y además permite 01:14:38
también identificar el nombre del fichero 01:14:42
en lugar de con una cadena de caracteres 01:14:44
aquí, fijaros, esto es un string 01:14:48
igual que lo hemos puesto aquí, entre comillas 01:14:49
podríamos haber definido una variable string 01:14:54
numFitch 01:14:56
aquí haber puesto el nombre del fichero 01:14:59
y haberse lo puesto aquí, ¿verdad? 01:15:02
que es un string, sería el mismo constructor, en ambos 01:15:05
casos sería 01:15:07
una cadena de caracteres, pero 01:15:08
está sobrecargado 01:15:11
el constructor de estos métodos para aceptar 01:15:13
también un objeto de la clase File. Entonces podemos poner aquí 01:15:17
New File, lo importamos 01:15:21
y ahora aquí en el constructor, en lugar de poner 01:15:33
esto, el nombre del fichero entre comillas como un string, lo podemos poner como un objeto 01:15:36
del método File. Bueno, podemos decir, pues esto es lo mismo, 01:15:40
¿no? Pues en este caso, a la hora de ponerse al constructor, bueno, pues es 01:15:44
lo mismo, pero esta clase nos permite hacer más cosas 01:15:48
como por ejemplo borrar un fichero, listar la información 01:15:52
de un directorio. Ya os digo, si nos da tiempo, lo hacemos hoy. 01:15:56
Y estas clases que tenemos por aquí 01:16:00
disponibles para acceder a ficheros, están 01:16:04
sobrecargadas para que en el constructor identifiquemos el fichero 01:16:08
sobre el cual queremos trabajar con un string o bien con un objeto 01:16:12
de la clase file. Otra clase que es más o menos 01:16:16
que tiene que responder 01:16:23
al término de serialización 01:16:26
tiene que ver con guardar 01:16:30
información de objetos que tenemos en nuestro 01:16:33
programa para poder recuperarlos. Fijaros 01:16:36
cuando nosotros hacemos un new de un objeto 01:16:39
de cualquier clase, ¿qué es lo que 01:16:42
sucede? Que ese objeto existe donde en memoria 01:16:45
RAM. Si nosotros apagamos el programa, perderemos su 01:16:48
información. ¿Qué tenemos que hacer? Pues hacer 01:16:51
esa información persistente. Podríamos guardarla en ficheros, 01:16:54
que es lo que vamos a hacer ahora, guardar cierta información 01:16:58
de objetos en ficheros, meterlos en una base 01:17:00
de datos para que fueran persistentes en una base de datos. La cosa 01:17:03
es que lo tendríamos que guardar en algún sitio. Si nosotros 01:17:06
ejecutamos un programa donde, no sé, 01:17:09
una tienda donde van los clientes 01:17:12
y ahora mismo hay tres clientes, o sea, en el momento de arrancar hay cero clientes, 01:17:16
damos de alta a tres clientes que están comprando en ese momento, 01:17:20
paramos el programa y lo volvemos a activar, pues la nueva activación, 01:17:23
esos tres clientes no existirán. ¿Por qué? Porque los teníamos en objetos en memoria RAM 01:17:27
y como la memoria RAM se libera cuando se cierra el programa, 01:17:31
la nueva ejecución no hemos hecho ningún new para ningún nuevo cliente. 01:17:36
Si queremos restablecer al mismo estado exactamente en el que se cierra la aplicación, 01:17:40
pues tendríamos que ser capaces de guardar esos clientes que estaban 01:17:44
y al arrancar la aplicación leer del sitio donde los hayamos guardado 01:17:48
para tenerlos de nuevo disponibles. 01:17:53
Una alternativa podría ser ir a atributo a atributo de esos objetos 01:17:57
y guardar la información de cada uno de los atributos, leerlos luego y cargarlos 01:18:01
hacer news de los objetos y cargarlos. Y otra, digamos más eficiente 01:18:05
es guardar el objeto en sí a través del proceso de serialización 01:18:09
que creo que os aparece en los apuntes 01:18:13
y bueno, vamos a hacer un pequeño ejemplo 01:18:18
porque es muy sencillo y se hace muy rápido 01:18:20
vamos a suponer que en este proyecto 01:18:22
tenemos la clase tan socorrida en tantos ejemplos 01:18:32
la clase persona 01:18:36
la clase persona tendría todos sus atributos 01:18:37
y todos sus métodos 01:18:44
vamos a entender que tiene 01:18:45
es un atributo donde tenga el nombre, también 01:18:47
socorrido siempre, ¿verdad? Y un entero donde tenga 01:18:53
la edad. Lógicamente tendría todos los métodos que correspondiesen. 01:18:57
La clase persona, aquí para la serialización no nos vamos a preocupar 01:19:05
mucho de ello. Vamos a dejarlo de momento así y no dedicamos más tiempo 01:19:08
a esto. Entonces aquí en el programa, pues como siempre 01:19:12
podríamos crear personas. Entonces decimos persona 01:19:16
igual a 01:19:21
new persona 01:19:23
aquí 01:19:25
podríamos tener un constructor copia 01:19:27
una inicialización, todo lo que fuese 01:19:29
ya os digo que no nos vamos a preocupar 01:19:31
mucho, vamos a darle unos datos aquí 01:19:33
de momento, ese nombre 01:19:35
p1.i edad 01:19:36
vamos a decir que no tiene 25 años 01:19:43
vamos a crear una segunda persona 01:19:46
y que vale, ya tiene 35 01:19:49
vale, pues ya tenemos aquí 01:20:05
dos personas 01:20:08
que por aquí seguirían 01:20:10
haciendo su lógica de programa normal 01:20:12
y resulta que si apagamos 01:20:13
el programa, pues esas dos personas 01:20:16
ahora mismo perderíamos toda su información 01:20:18
¿por qué? pues porque está en memoria RAM 01:20:20
que se ha reservado, como hemos 01:20:22
dicho tantas veces, en el momento en el que hemos hecho 01:20:24
el new y se ha inicializado 01:20:26
a través del 01:20:27
constructor persona 01:20:28
por defecto en este caso, porque no lo hemos 01:20:31
programado. Tengo comentado más cosas de las que debiera 01:20:33
por ahí y no me compila. Vale, ya compila. 01:20:42
Vale, pues para guardar información 01:20:50
que queramos tener en un momento dado de diferentes 01:20:54
clases que tengamos en el programa, podemos utilizar 01:20:58
las clases Object Output Stream. 01:21:01
A ver dónde estaba por ahí. 01:21:09
OutputStream, ObjectOutputStream 01:21:10
para guardar información, para enviar 01:21:15
a través de un flujo objetos y 01:21:19
el ObjectInputStream para leerlos. Imaginaos que estamos 01:21:23
comunicando dos aplicaciones. Pues en una podríamos implementar 01:21:27
el ObjectInputStream para coger streams que serán objetos 01:21:32
y desde la otra hacer el ObjectOutputStream. Esto es para 01:21:35
comunicar dos aplicaciones que están en marcha y queremos pasarle ciertos objetos de la clase 01:21:41
persona de una a otra para que la segunda tenga la información de los objetos que se han dado de 01:21:46
alta en la primera. Otra posibilidad sería, oye mira, los objetos que tenemos a través de un 01:21:51
object output stream vamos a guardarlos en un ficherito. Entonces podríamos definir un fichero 01:21:58
file output stream, vamos a escribir un stream en un fichero de salida 01:22:04
y a este decirle que la información 01:22:08
le va a venir desde un object output stream 01:22:13
es decir, el object output stream se va a guardar en un fichero, con lo cual 01:22:17
estos en lugar de enviárselos a otra aplicación, en este caso lo estaríamos dejando registrados 01:22:20
en un ficherito y luego en una siguiente ejecución de la aplicación 01:22:24
o desde otra aplicación, lo que haríamos sería 01:22:29
desde un fichero, un FileInputString, leer la información 01:22:32
como si fueran objetos a través de la clase ObjectInputString 01:22:37
y ahí ya los damos de alta de nuevo como objetos 01:22:41
del programa, en este caso objetos de tipo persona 01:22:45
entonces si cogemos y primero hacemos 01:22:49
el almacenamiento, lo que diremos, mira vamos a guardar información en un 01:22:53
fichero, decimos FileOutputString 01:22:57
fijaros que ahora no vamos a encapsular esto como como readers ni como writers porque pues porque 01:23:03
queremos guardar los objetos como bytes directamente no queremos que tengan un formato para procesarlo como caracteres 01:23:10
podemos poner el file output stream 01:23:19
igual a new y aquí el fichero vamos a llamarlo 01:23:22
vamos a llamarlo que deciros 01:23:34
personas persona punto obj obj lo voy a llamar por objeto al nombre del fichero esto es algo 01:23:36
esto no va a permitir escribir un stream en forma de salida en un fichero pero el origen de esa 01:23:55
información de dónde va a venir pues va a venir de un objeto de lo que vamos a hacer va a ser 01:24:02
escribir sobre objetos, object, object output stream, output stream por aquí, el object output stream 01:24:06
y este object output screen queremos que en particular se dirija a un ficherito que hemos 01:24:16
dado de alta aquí. Eso lo indicamos ahí en el constructor. Importamos y decimos que añada el 01:24:46
excepción aquí como clave y ahora lo que vamos a hacer aquí es que sobre el oye output stream lo 01:24:55
que haga es que escriba nos da diferentes opciones por aquí pero lo que nos interesa es que escriba 01:25:07
un objeto veis y qué objeto vamos a querer que escriba pues mira vamos a decirle que escriba 01:25:13
el objeto P1 y le vamos a decir que escriba el objeto 01:25:20
P2. Hacemos un flush 01:25:29
y lo vamos a cerrar. Aquí lo que estamos haciendo es 01:25:36
utilizando esta clase que se ha especializado en escribir información de objetos 01:25:44
lo encasulamos dentro 01:25:48
de una clase que escribe streams en un fichero y ahora 01:25:52
hacemos las escrituras a través del writeObject 01:25:56
en un ficherito que se va terminando 01:25:59
llamando persona.obj 01:26:03
y me dice aquí 01:26:05
la clase persona no es serializable 01:26:08
entonces no tejo 01:26:11
os acordáis de la palabra 01:26:13
serializable que decíamos 01:26:15
esto es porque aquellas clases 01:26:16
que vayamos a utilizar para escribir como 01:26:19
objetos, tenemos que 01:26:21
indicarles que implementen 01:26:22
un interfaz 01:26:25
es el 01:26:26
implements 01:26:27
serializable, lo importamos 01:26:28
y ya está, fijaros que hay que implementar el interfaz, las librerías 01:26:38
de Java por estos métodos lo precisarán 01:26:42
pero en realidad no tenemos que sobrescribir ningún método, que normalmente lo que 01:26:46
nos obligan los interfaces es luego a sobrescribir métodos, pues no hay que sobrescribir 01:26:50
nada, simplemente hace referencia a que implemente serializable 01:26:55
para que no se nos queje aquí, lo vamos a ejecutar por aquí 01:26:58
parece que no se ha quejado con errores 01:27:04
vamos a ver si existe el fichero persona.bj 01:27:08
ahí está, y fijaros, tiene ahí datos 01:27:11
bueno, pues que él se las ha arreglado para guardarlo 01:27:18
como haya sido, no son datos legibles 01:27:21
desde nuestra perspectiva humana 01:27:25
sí que es verdad que hay cosillas por ahí que parece que 01:27:27
se quieren leer, iría por ahí, pero no es 01:27:30
entendible al 100%, bien pues ya tenemos 01:27:33
guardado eso. ¿Qué sucede? Que ahora podría interesarnos 01:27:38
en otra ejecución del programa, arrancarlo bajo 01:27:42
esta situación. 01:27:45
Se me ha colgado esta máquina, la máquina virtual. 01:27:50
No voy a andar dándole mucha vuelta, la voy a parar y la voy a arrancar de nuevo. 01:28:03
Lo que vamos a hacer ahora va a ser, os cuento mientras arranca, 01:28:19
irnos al input, a través 01:28:25
de un file inputString, hacer un object inputString para cargar 01:28:30
esos datos que hemos guardado antes, a ver, espero que no se nos hayan perdido 01:28:33
los datos que teníamos guardados del proyecto, a ver, a ver 01:28:47
por aquí estábamos, entonces ahora cogemos 01:29:14
voy a comentar esto, se supone que viene otro 01:29:33
programa, viene este, en otra ejecución, lo que queremos hacer es 01:29:37
oye mira, vamos a arrancar partiendo del estado en el que 01:29:41
pudo parar aquel programa que era con estos dos objetos cargados, entonces para eso lo que hacemos ahora es definir un FileInputStream, 01:29:45
este FileInputStream queremos leer la información que tiene este fichero que habíamos guardado antes en disco, vamos a volver aquí al directorio, 01:30:04
recordad que teníamos el fichero este con esa información 01:30:29
que bueno, no se entendía muy bien, y le había guardado el 01:30:39
file output stream, queremos volver 01:30:43
a leer el mismo ficherito, nos va a obligar a hacer un try catch 01:30:48
por aquí, y lo queremos leer en formato 01:30:56
de objetos, fijaros que es un poco el reflejo de esto 01:31:02
aquí teníamos el file output stream, file input stream 01:31:06
y ahora el object 01:31:09
output stream, pues que pondremos aquí 01:31:11
un object 01:31:12
input stream 01:31:13
new 01:31:16
y a este 01:31:29
object input stream le metemos 01:31:31
el file input stream 01:31:33
importamos, añadimos 01:31:34
la cláusula 01:31:46
por aquí del iobsection 01:31:48
y ya estamos en disposición de leer 01:31:49
objetos 01:31:51
el object input stream 01:31:52
lo hacemos 01:31:58
si aquí hacíamos 01:31:58
un write 01:32:01
pues aquí 01:32:03
entiendo que será un read object 01:32:04
read object 01:32:07
y lo que nos devuelve es un objeto 01:32:08
del tipo que 01:32:10
toque, fijaros que devuelve 01:32:12
algo como 01:32:18
object, es decir es genérico total 01:32:20
entonces como lo que vamos a leer 01:32:22
va a ser una persona, vamos a hacerle aquí un casting 01:32:24
para que 01:32:26
convierta la referencia 01:32:28
object a una referencia a la clase persona y ahora lo que podemos hacer aquí es definir persona 01:32:31
per una leída, fijaros no lo hago un new, directamente simplemente es un dedito para apuntar donde toque 01:32:38
y decimos que apunte a la posición de memoria que nos diga esto, read object nos dice que 01:32:49
añadíamos la cláusula, dice class no phone exception, 01:32:58
también la necesita, entonces esta persona 01:33:04
estará apuntando a un objeto 01:33:08
que acabaremos de leer de aquí, que por la secuencia 01:33:11
de la escritura anterior, pues será la misma información que tenía P1, 01:33:16
P1 recordad que antes cuando lo hemos escrito era NOA con edad de 25, 01:33:20
entonces se entiende que ahora PER1 leída estará 01:33:24
apuntando a los datos que antes habíamos guardado en el fichero para NOA P1. 01:33:27
Vamos aquí a hacer un System of Println y ponemos aquí edad también. 01:33:35
Hemos cargado aquí la información desde el fichero a través de esta lectura 01:34:09
que sabemos porque es un fichero que hemos creado nosotros antes 01:34:13
que corresponde a esta escritura de un objeto de una clase persona P1 01:34:17
a la que le habíamos dado estos datos 01:34:23
y ya que habíamos guardado dos, pues vamos a hacer una lectura 01:34:26
del fichero de la segunda de las personas 01:34:33
y repetimos 01:34:34
toda la jugada, volvemos a hacer una lectura 01:34:37
ahora la lectura del siguiente, porque 01:34:44
en este avanzó el cursor 01:34:46
en el fichero y se quedó pendiente de la lectura 01:34:47
de la segunda de las personas 01:34:50
entonces ejecutamos por aquí 01:34:51
y fijaros como efectivamente nos ha mostrado los datos 01:35:00
de la lectura 01:35:06
con una edad de 0 01:35:07
edad 0 01:35:09
1, 1, 2, 2, no ha funcionado bien del todo esto, fijaros como nos está diciendo que no, tiene edad 35, que tenía 25, y Valeria no dice edad 0, que tenía 35 01:35:13
vamos a borrarlo, vamos a hacer otra ejecución creando el fichero de nuevo, porque como estamos tocando el código no vaya a ser que hayamos liado alguna 01:35:46
voy a volver a guardar los datos p1 p2 ejecuto ya está persona bj y ahora les comento esta otra 01:36:09
parte que es en la que estamos leyendo pues nada me da estos datos no sé qué estoy haciendo mal 01:36:29
algo algo estoy haciendo mal no sé si entiendo que veis lo que está pasando porque cuando guardo 01:36:40
los datos, guardo, ah vale 01:37:00
mirad 01:37:03
vale, aquí está la explicación, es que al guardarlo 01:37:03
estoy guardando aquí P1 edad 01:37:07
no estoy modificando P2 edad 01:37:09
sino P1 edad 01:37:11
entonces P2 edad vale 0 01:37:12
efectivamente, y P1 edad 01:37:15
lo estoy sobrescribiendo a 35 01:37:17
vale, que bueno 01:37:18
es que las cosas tengan explicación 01:37:21
aquí tengo un error 01:37:23
he mantenido P1 del copy-paste anterior y esto tiene que ser 01:37:24
P2, lo voy a borrar de nuevo 01:37:27
vamos a hacer una ejecución 01:37:33
porque no tiene esto mucho más misterio 01:37:34
como para que no funcione, descomento de nuevo para guardar 01:37:39
el fichero, el fichero ahora 01:37:48
persona obj no está existiendo, le doy una ejecución 01:37:50
ya tenemos ahí persona obj, después de haber hecho el cambio de ese error que teníamos 01:37:55
en el programa, me vengo por aquí, descomento para la lectura 01:38:02
y bueno, ahora ya sí que coge los datos desde el fichero 01:38:13
como era de esperar, para la persona 1 01:38:21
dice que es nueva con edad 25 01:38:23
y la persona 2 que es Valeria con edad 35 01:38:24
bueno, pues esa sería una posibilidad 01:38:27
de, dentro de todas 01:38:31
estas, en este caso de guardar 01:38:33
objetos, y fijaros 01:38:34
que bueno, pues hemos visto unas 01:38:36
cuantas, yo en verdad muchas 01:38:38
no sé exactamente para qué sirve, no las he 01:38:40
utilizado, pero hay muchas más 01:38:42
alternativas dentro de las librerías 01:38:44
las librerías son inmensas 01:38:46
las que tiene disponible Java, no solamente 01:38:48
en este ámbito, y estas 01:38:50
que os cuento, pues bueno, son un poco las que aparecen en la teoría y quizás las que 01:38:52
son más utilizadas, pero bueno, pues hay más por ahí que 01:38:56
estarán pensadas para algunas situaciones más en particular. 01:39:00
Aquí hemos, bueno, aquí hay 01:39:07
otra clase de la que habla también un poco la teoría, que es para accesos 01:39:10
random a posiciones aleatorias, no tanto 01:39:14
lo que hemos hecho ahora ha sido cuando escribimos 01:39:18
o leemos de un fichero, estamos haciendo un acceso 01:39:22
secuencial, es decir, si estamos escribiendo, si tenemos 01:39:26
un attach, pues escribe justo al final y la siguiente escritura 01:39:29
después y la siguiente después, siempre debajo. Cuando lo leemos 01:39:34
de igual forma, digamos que al abrir el fichero, el puntero 01:39:38
se pone en el primero de los registros, leemos ese registro y una vez leído ese registro 01:39:42
avanza al segundo registro, leerá el segundo registro, avanzará al tercero 01:39:46
así hasta que llegue el final de fichero 01:39:50
que normalmente se lee 01:39:52
la finalización de los flujos 01:39:54
como bien comentabais antes alguno 01:39:56
te devuelve un menos uno la lectura 01:39:58
típicamente 01:40:00
y existe la posibilidad de acceder a 01:40:01
ficheros de forma aleatorio, léeme 01:40:04
directamente un registro que esté en la posición 01:40:06
la que sea, si tienes la posibilidad 01:40:08
del programa de conocerlo, pues eso 01:40:10
se podrá gestionar desde 01:40:12
la estructura 01:40:14
esta de árbol de random access file 01:40:16
bueno, para meter tokens 01:40:18
por aquí que diferencien unos tipos de datos 01:40:23
de otro, para, imaginaos que en un fichero queréis meter 01:40:25
enteros, doubles, strings 01:40:28
todo mezclado, hay uno detrás de otro, pues se puede 01:40:32
tokenizar, es decir, poner identificadores 01:40:34
de cada uno de los datos, creo recordar que era esta clase 01:40:37
y la otra que 01:40:41
se trata en el tema y que también tiene cierto interés 01:40:44
es la file esta que os la he referido 01:40:47
porque a la hora de definir el fichero al que se quiera acceder 01:40:49
En el constructor se puede poner como un string o como un objeto de la clase File, pero es capaz de hacer bastante más cosas. 01:40:53
Y no sé si que empecemos a hacer algo 10 minutillos, yo creo que sí. 01:41:01
Y hasta donde nos dé tiempo estos 10 minutillos. 01:41:08
A lo mejor hasta nos da tiempo a, por lo menos, hacer un esbozo. 01:41:14
Mira, la clase File nos permite... 01:41:25
Mira, vamos a definirlo... 01:41:34
Vamos a poner aquí un string. 01:41:37
ese no un fich y hacia aquí en donde empieza el proyecto vamos a crear por ejemplo un fich un 01:41:38
directorio comando para crear un directorio de consola es el mkdir de inglés me director y 01:41:58
y vamos a poner aquí tenemos ahora esto un directorio si ponemos el s menos se lea para 01:42:07
que nos dé más detalles con el atributo lea el comando ls de linux vemos que 01:42:14
medir es efectivamente un directorio y que estos otros que tenemos por aquí 01:42:19
pues son ficheros lo indica aquí con un guioncito entonces vamos a poner a poner 01:42:24
un punto aquí no vamos a poner aquí vamos a empezar poniendo a medir que es 01:42:33
un directorio. Si yo cojo y digo aquí file, mi file igual a new file, aquí podría poner un string en 01:42:42
el constructor del file o un string que contenga o una variable de tipo string que contenga una 01:43:00
cadena de caracteres. Pues mi file nos permite validar cosas como por ejemplo estas. Podemos 01:43:07
decir mi file que es un objeto de la clase file que está referenciando a medir punto is es un 01:43:14
directorio es un fichero imaginaros que nos interesa es un es un fichero oculto vamos a 01:43:25
probar estas es un directorio es un directorio que nos devolvía nos devolvía entiendo si es una 01:43:34
pregunta, nos devuelve un boolean, es decir, true si es un directorio o false si no lo es. 01:43:39
Entonces, por ejemplo, podríamos aquí hacer una comprobación. En el contexto de un enunciado, 01:43:47
pues podríamos tener que validar en un momento dado si algo es un directorio o no es un directorio. 01:43:53
Lo podríamos comprobar así, diciendo, ¿es un directorio? Vamos a poner aquí un... 01:43:59
Y aquí podemos decir, ese nom es un directorio. 01:44:12
Voy a hacer un copy-paste de esto aquí. 01:44:26
Igual que estamos validando aquí si es un directorio, podríamos decir, is es un fichero. 01:44:29
De igual forma, aquí será true si es un fichero. 01:44:36
En este caso, midir hemos visto que no, que es un directorio. 01:44:39
Con lo cual, es previsible que aquí diga, es un directorio. 01:44:43
vamos a ponerlo aquí para el false, indicando 01:44:46
diciendo que no es un fichero 01:44:56
y aquí no es un directorio 01:45:00
entonces si hacemos una ejecución ahora, pues nos dice 01:45:11
es un directorio, no es un fichero, vale, pues lo previsible 01:45:15
mirad, aquí tenemos que fichlet es 01:45:20
un fichero, entonces si cogemos y en lugar de validar este 01:45:24
decimos que nos valide fichlet, pues nos dirá 01:45:28
no es un directorio, es un fichero. Bueno, pues un método que nos permite 01:45:30
comprobar una cosa o nos permite comprobar 01:45:35
otra. Otro de los métodos que tiene 01:45:38
punto exist. También nos dejó un boolean y dice 01:45:45
¿existe o no existe? Existe, no existe. 01:46:00
Bueno, podría interesarnos en un momento dado. Dice 01:46:14
existe efectivamente y si aquí le decimos ese otro le añado un uno al nombre que ese ficherito no 01:46:16
existe pues dice no es un director no es un fichero y además no existe bueno métodos que están ahí 01:46:22
disponibles pues para poder utilizar en un momento dado aquí he vuelto a poner este fichlet si hacemos 01:46:32
aquí un ls aquí tenemos el fichlet.txt si hacemos una ejecución ahora mismo efectivamente nos dice 01:46:42
que es un fichero y que existe, pues bueno, otra de las opciones 01:46:55
que tenemos en la clase File 01:46:58
es mi file 01:47:01
punto, no sé si es remove o delete 01:47:04
pues no, delete 01:47:07
y esto que hace, pues nos borra un fichero, ¿qué fichero borra? 01:47:10
pues al que está apuntando, entonces si ahora hacemos un delete 01:47:13
aquí del fichero, pues luego no va a decir que no existe 01:47:16
porque lo va a borrar, ejecuto, ya me dice 01:47:20
que no existe por aquí y de hecho si nos venimos ahora ya aquí el fichero que era fichlet, veis 01:47:27
cómo se lo ha cargado, pues desde el programa podemos borrar un fichero. He entrado dentro del 01:47:34
directorio midir, este que había creado, proyecto directorio midir y vamos a hacer, vamos a crear 01:47:44
el comando touch en linux crea ficheros vacíos, los crea sin ninguna información pero ahí los 01:47:50
crea vale entonces vamos a llamarlo 1 punto txt vamos a hacer un touch de 2 sea un ls fijaros 01:47:57
cómo existen aquí estos dos ficheritos ahora me interesa que existan los ficheros sin información 01:48:09
por el momento por eso lo hecho con este comando todo mucho entonces ahora podemos decir que a este 01:48:15
directorio medir y a comentar todo este bloque que ya está visto podemos un listado de toda su 01:48:22
información y para ver el listado de su información lo que vamos a utilizar es 01:48:40
el método list el método list ponemos aquí mi file punto list fijaros que lo 01:48:46
que devuelve es un array de strings tiene sentido no nos va a devolver el 01:48:54
nombre de cada uno de los elementos que están en ese directorio como pueden ser 01:49:00
más de uno aquí tenemos en este caso tenemos dos en 01:49:03
este directorio, pues nos devuelve un array. Entonces para cargar la información en ese 01:49:08
array, lo que hacemos para cargar la información que tiene ese directorio, vamos por aquí, y nos 01:49:15
devuelve la información un array. Entonces definimos un string, ese info.dir, no me vale que sea un 01:49:22
string, necesito que sea un array de strings. Fijaros que no hacemos el new porque este método 01:49:29
ya se estará preocupando de hacerlo. Y ahora, bueno, esto no deja de ser 01:49:37
un array de strings que se habrá cargado con el contenido que tiene 01:49:43
el directorio donde en este momento está apuntando 01:49:47
file, que es midir. Sabemos, por otra parte, que tiene estos 01:49:51
dos elementos. Podríamos hacer un for, ¿verdad? 01:49:55
Para recorrer todos los elementos de un array. Decimos int i 01:49:59
igual a cero, mientras i sea menor 01:50:02
que el número de elementos que tiene el array 01:50:06
punto length 01:50:09
hacemos un y más más 01:50:10
aprovechamos con system.out.println 01:50:14
para recordar que es un flujo 01:50:29
de datos también 01:50:31
en este caso de salida del fichero 01:50:32
y escribimos el contenido del array 01:50:35
ahí lo tenemos, entonces si hacemos una ejecución 01:50:37
ahí lo tenéis 01:50:43
nos ha mostrado el listado de contenidos 01:50:46
que tiene 01:50:48
que conclusión llevamos, que file 01:50:49
lo que nos permite es hacer gestiones sobre elementos que tenemos en el sistema de archivos, 01:50:52
no tanto como para leer o escribir, que para eso tenemos un montón de clases por aquí, 01:51:03
sino para hacer otro tipo de gestiones con ellos, borrarlos, crearlos, eliminar un fichero. 01:51:08
otra de las opciones que tenemos fijaros vamos a hacerla es mi file punto mkdir para crear un 01:51:14
directorio crea el directorio este entonces vamos a decirle que cree el directorio dir nuevo perdón 01:51:23
claro esto el mkdir no lo podemos pasar aquí sino que lo que tenemos que hacer el directorio que 01:51:39
crea es el que tiene el file, vamos a crear un file, un nuevo file, mi file 2 y vamos a decir que el 01:51:47
directorio que queremos crear es un directorio que se llame hola, va a crear el directorio hola 01:51:54
en la ruta que tenemos por defecto, en principio será aquí, le damos aquí una ejecución, me ha dicho 01:52:12
el 1 y el 2 del otro sitio y ahora decimos aquí un ls y fijaros como tenemos ya el directorio hola 01:52:23
por aquí, a ver si ponemos aquí 01:52:29
punto barra, vamos a hacer esta prueba para ver si podemos crear el directorio 01:52:39
hola en el sitio donde nos encontramos en el proyecto 01:52:46
barra midir para intentar crear el directorio hola dentro de midir 01:52:50
que en este momento no existe, como podéis ver, le damos aquí una ejecución 01:52:54
y a ver si funciona, bueno, de hecho ha funcionado porque 01:52:58
ya el programa me lo está chivando aquí al hacer el recorrido del contenido de ese 01:53:03
directorio pues aquí una ls y veréis cómo ha creado el directorio hola por aquí también 01:53:07
y bueno nos ha quedado mucho la verdad de aquí quería contaros también cómo podíamos hacer para 01:53:18
a la hora de mostrar un listado file tienen bastante más opciones pero ahora demostrar un 01:53:24
listado se puede poner un filtro para que nos muestre todo el contenido pues sólo los que 01:53:29
tengan txt son los que empiecen por alguna forma existe una forma para hacer eso y que poder 01:53:32
generar un filtro sobre el contenido que nos devuelva list pero esto sí que lo dejamos ya 01:53:39
para arrancar la próxima tutoría y con eso y ya vamos a ver qué hacemos no sé si el plan de ver 01:53:45
los interfaces gráficos si no tenéis ninguna otra cosa por ahí que queréis que repasemos 01:53:52
ya terminamos la última tutoría la semana que viene alguna cosita antes de cerrar hoy que ya 01:53:57
son y media que nos estamos yendo de hora y van a venir los compis por aquí a ver vamos a ver 01:54:04
supongo rosa este enunciado cierto es a ver por dónde andamos desarrolló un programa luego no 01:54:41
estamos usando por ahí abajo que a ver la idea es leer lo que intenta plantear el enunciado es 01:55:08
lee el fichero usuarios y guarda su información podrías crear un array de strings pero lo que 01:55:14
te dice es que hagas pues un array de un array o que lo guardes no entiendo que será en un array 01:55:21
no me acuerdo ahora mismo de anunciado muy bien que lo guardes en como objeto de la clase usuario 01:55:27
que básicamente tienen el nombre no tiene más nombre y apellidos o sea esto estos nombres al 01:55:34
leer el fichero, los podría guardar en 01:55:45
un array de strings, ¿no? 01:55:47
Entonces, lo que te estoy diciendo aquí al enunciado es que 01:55:49
en lugar de un array de strings, pues 01:55:51
crees una clase de usuario, que 01:55:53
básicamente, no sé si 01:55:55
nos hace falta. 01:55:56
Sí, no sé si nos hace falta mucho más 01:55:59
por ahí. De tal forma, 01:56:01
también te digo que 01:56:04
si ves un diseño alternativo 01:56:07
y dices, pues mira, yo creo que es más 01:56:09
cómodo hacer lo que nos está pidiendo 01:56:11
directamente con lo que voy leyendo en un array 01:56:13
de strings, en lugar de crear una clase 01:56:15
usuario, pues en las prácticas hazlo, ¿sabes? 01:56:18
No te digo tanto que vayas tan 01:56:21
por libre en el examen, porque ahí sí que a lo mejor si ponemos, pues crea 01:56:24
un conjunto, una colección que sea de tipo conjunto 01:56:27
pues no me hagas una release, por ejemplo, ¿vale? Pero 01:56:30
aquí en las prácticas, al final, lo importante es practicar 01:56:33
entonces, bueno, pues igual esto está sobredimensionado, crear una 01:56:36
clase usuario, cuando realmente los usuarios solo tienen 01:56:39
un string, ¿no? Que pueda ser nombre y apellidos 01:56:42
pues si quieres implementarlo así, ¿sabes? 01:56:44
me pones si quieres un comentario ahí en la tarea 01:56:47
pues en lugar de crear una clase 01:56:48
he hecho esto, y si no, pues 01:56:50
si quieres crear la clase usuario que tenga simplemente 01:56:52
el atributo stream 01:56:54
que sea nombre y apellidos y ya está 01:56:55
vale, pues nada, pues ya cerramos 01:56:58
con esto por hoy 01:57:05
os sigo atendiendo por los foros 01:57:05
y la semana que viene nos vemos el lunes por aquí de nuevo 01:57:08
Materias:
Programación
Niveles educativos:
▼ Mostrar / ocultar niveles
  • Formación Profesional
    • Ciclo formativo de grado superior
      • Primer Curso
Autor/es:
JM
Subido por:
Jose Manuel M.
Licencia:
Dominio público
Visualizaciones:
30
Fecha:
5 de mayo de 2025 - 19:36
Visibilidad:
Clave
Centro:
IES ALONSO DE AVELLANEDA
Duración:
1h′ 57′ 15″
Relación de aspecto:
1.78:1
Resolución:
1920x1080 píxeles
Tamaño:
251.49 MBytes

Del mismo autor…

Ver más del mismo autor


EducaMadrid, Plataforma Educativa de la Comunidad de Madrid

Plataforma Educativa EducaMadrid