2025-05-05-Programacion - 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:
Tema 10 - Repaso Flujos de datos
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
s
01:14:55
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
p1
01:19:18
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