20260313 Ficheros_1 - Contenido educativo
Ajuste de pantallaEl ajuste de pantalla se aprecia al ver el vídeo en pantalla completa. Elige la presentación que más te guste:
Vale
00:00:00
A ver
00:00:13
Persistencia
00:00:16
¿Vosotros qué os gusta organizar vuestra vida en temas?
00:00:19
Pues sería un tema
00:00:28
¿Vale?
00:00:29
¿Qué es la persistencia de datos? La persistencia de datos consiste en que los datos que mi aplicación maneja sean, valga la redundancia, persistentes.
00:00:31
o lo que es lo mismo
00:00:46
que yo pueda vivir despreocupada
00:00:48
de cuando mi aplicación
00:00:51
reinicia, se apaga
00:00:52
la dejo apagada
00:00:55
porque estoy instalando una versión nueva
00:00:56
lo que sea, pueda vivir despreocupada
00:00:58
de que esos datos que mi aplicación maneja
00:01:00
se van a perder
00:01:02
¿vale?
00:01:03
normalmente las aplicaciones lógicamente
00:01:06
trabajan con las colecciones
00:01:08
de usuarios, de password, de lo que sea
00:01:10
todo eso está almacenado
00:01:12
en algún sitio, sean ficheros
00:01:14
sean bases de datos. Nuestra aplicación trabaja con esos datos, pero nuestra aplicación jamás
00:01:15
trabaja con los datos directamente en el soporte de almacenamiento, sea base de datos o fichero,
00:01:21
¿verdad? Sea una base de datos o sea un fichero, que es donde realmente están los datos de
00:01:28
mi aplicación, usuarios, contraseñas, mis facturas, sean los que sean, mi programa
00:01:34
java jamás
00:01:40
va a trabajar con ellos
00:01:43
directamente aquí, es imposible
00:01:45
porque mi aplicación java
00:01:46
solamente puede trabajar
00:01:48
modificar, crear, eliminar
00:01:50
solamente puede trabajar
00:01:53
con datos que estén
00:01:55
en la memoria RAM, solamente
00:01:56
¿vale? entonces nosotros
00:02:00
hasta ahora, pues todas
00:02:02
nuestras aplicaciones
00:02:04
creaban los datos de nuevas, de buenas
00:02:05
a primeras, los creaban
00:02:08
¿Cómo? Pues insertándolos por consola
00:02:10
Los insertábamos por consola en ese momento
00:02:13
Y se creaban
00:02:15
Y ya está, entonces nuestra aplicación estaba
00:02:17
Condenada a que hubiera siempre un tío delante
00:02:19
Sentado para meter
00:02:21
Los datos y en ese momento crear los datos
00:02:23
En memoria RAM, operar y hacer
00:02:25
Lo que fuera
00:02:27
Cuando la aplicación terminaba, pues lógicamente
00:02:28
Todos estos datos
00:02:31
Pues han desaparecido
00:02:32
Luego, lo más que ha
00:02:34
Podido ocurrir es que el resultado
00:02:37
lo hayamos visto
00:02:39
en la consola
00:02:40
entonces de nuevo nuestra aplicación está condenada
00:02:42
que haya un tío ahí sentado
00:02:45
esperando que la aplicación muestre
00:02:46
las cosas en la consola para que él vaya
00:02:49
a, vale, viendo esos resultados
00:02:51
bueno
00:02:53
pues esa es una aplicación que no
00:02:54
tiene persistencia, ¿vale?
00:02:57
entonces bueno, en ciertos contextos
00:02:59
pues ya está, yo meto los datos y obtengo el resultado
00:03:01
que quería, ¿vale? no tiene persistencia
00:03:03
bueno, pero claro
00:03:05
no es lo habitual, lo habitual en una aplicación
00:03:07
es que la aplicación trabaje
00:03:09
con datos que están
00:03:11
en algún sitio, pues como hemos dicho
00:03:13
antes del tipo, un montón de facturas
00:03:15
de usuarios, de contraseñas, todo eso
00:03:17
no lo podemos introducir cada vez
00:03:19
que la aplicación arranca, lógicamente lo podemos
00:03:21
introducir, todo eso son millones
00:03:23
de datos que están en algún sitio
00:03:25
sea base de datos o fichero
00:03:27
que no se pierde nunca, ahí están
00:03:29
pero mi aplicación no puede
00:03:30
trabajar con ellos, entonces mi aplicación
00:03:33
los tiene que volcar de alguna manera
00:03:35
a variables
00:03:37
cuando ya
00:03:40
estén volcados, mi aplicación trabaja
00:03:42
con ellos
00:03:44
y cuando mi aplicación se cierra
00:03:44
de alguna manera, pues eso tiene que ir
00:03:47
otra vez al soporte
00:03:50
pues esa tarea
00:03:51
no es trivial
00:03:54
claro, esa tarea de
00:03:55
hacer esa conexión
00:03:57
esa sincronización entre lo que hay
00:03:59
aquí y lo que hay aquí, hacer esa sincronización
00:04:02
para que mi aplicación
00:04:04
trabaje con estos datos
00:04:06
sabiendo que son los que
00:04:07
realmente están aquí
00:04:10
y que cuando la aplicación termina sepa
00:04:11
que estos datos vuelven aquí
00:04:14
pues esa sincronización
00:04:16
no es trivial
00:04:17
si la conseguimos hacer
00:04:18
eso es lo que convierte a una aplicación
00:04:21
en una aplicación persistente
00:04:24
entonces una aplicación persistente
00:04:26
trabaja con sus datos en memoria RAM como todas
00:04:32
porque tienen que estar ahí, no hay otra
00:04:34
Trabaja con sus datos en RAM
00:04:36
Pero estos datos de alguna manera
00:04:38
Estarán sincronizados con los que están aquí
00:04:41
De alguna manera
00:04:43
Y ese de alguna manera
00:04:44
Pues ahí ya se abre
00:04:49
Se abre un mundo gigantesco
00:04:51
Y ese de alguna manera
00:04:54
Ese tenerlo conectado
00:04:56
Ese cómo me aseguro yo
00:04:58
Que aquello con lo que trabajo
00:05:00
Es lo que estaba aquí
00:05:01
Cómo me aseguro yo
00:05:02
Que los cambios que haga
00:05:04
Se guardan aquí
00:05:05
¿Y ese de alguna manera cómo hago esta sincronización?
00:05:06
Pues eso es un mundo gigantesco
00:05:11
y es, para que no os hagáis ilusiones,
00:05:14
no lo vamos a ver ahora,
00:05:19
porque para eso está un módulo entero de segundo
00:05:21
que es exclusivamente eso,
00:05:24
que se llama acceso a datos.
00:05:26
Entonces, este módulo de segundo es exclusivamente eso.
00:05:29
¿Por qué?
00:05:33
porque para eso hay todo un mundo entero
00:05:34
de frameworks, porque
00:05:36
de hacer bien esta sincronización
00:05:37
depende que mi aplicación
00:05:40
tenga sentido o sea una caca
00:05:42
de hacer bien esta sincronización
00:05:44
porque lo que sí que está
00:05:46
claro es que lo que no vamos a poder eludir
00:05:48
salvo en aplicaciones muy de mierdecilla
00:05:50
sencillas, lo que no vamos a poder eludir
00:05:52
es que mi aplicación trabaje con un modelo
00:05:54
de base de datos bestial
00:05:56
eso no lo vamos a poder eludir
00:05:58
que trabaje con una base de datos con tropecientas mil
00:05:59
tablas, con relaciones, con cosas.
00:06:02
Eso no se va a poder eludir. Cualquier aplicación va a
00:06:04
tener una base de datos con 30.000 tablas.
00:06:06
Entonces, la tarea
00:06:09
de yo hacer mi humilde aplicación
00:06:10
con sus variables aquí y que
00:06:12
eso automáticamente
00:06:14
quede reflejado en el soporte
00:06:15
permanente, pues eso
00:06:18
como no es trivial, hay tropecientos mil
00:06:20
frameworks. Cuando digo
00:06:24
frameworks me refiero a clases
00:06:26
que hay que configurar, que usar
00:06:28
para simular precisamente esto,
00:06:29
para simular ese efecto de persistencia, ¿vale?
00:06:33
Y eso, pues bueno, se ve todo eso
00:06:36
en este módulo entero de segundo, ¿vale?
00:06:39
Entonces, ¿aquí qué vamos a hacer ahora?
00:06:42
La parte que queda para primero
00:06:45
es como una especie de
00:06:46
yo puedo querer hacer mi persistencia si quiero,
00:06:49
es decir, quiero tener la posibilidad
00:06:52
de guardar mis cosas y que no se pierdan,
00:06:54
pero de una manera más sencilla,
00:06:57
No tengo por qué recurrir siempre a frameworks gigantescos porque no siempre tengo una base de datos con 200.000 tablas. Hombre, también quiero yo, si me hago mi aplicación con mis libros, mis cosas, pues poder guardarlo en un fichero y tenerlo ahí que cuando la aplicación arranca vuelva otra vez, ¿vale? También sería una aplicación persistente, pero hecha más a mano por nosotros, ¿vale?
00:06:58
Bueno, pues, ¿qué parte queda para primero entonces? Pues en lugar de guardar los datos en base de datos y sincronizarnos con una base de datos, hacerlo en fichero, que también puede ser perfectamente.
00:07:18
Es decir, los datos de mi aplicación
00:07:33
Estos datos que están aquí en la memoria RAM
00:07:42
Pues yo tengo mis objetos, mi lista de objetos
00:07:45
Lo que sea, lo tengo ahí
00:07:50
Yo quiero que cuando la aplicación termine eso se quede guardadito
00:07:51
Bueno, pues podemos escribirlo en un fichero
00:07:53
Y ya está
00:07:57
Cuando mi aplicación arranca yo puedo programarlo
00:07:58
Para que lo primero que haga sea si este fichero existe
00:08:02
Porque hay ya datos iniciales
00:08:05
Pues antes de nada, cárgame los que hay.
00:08:06
Y yo aquí trabajo y hago mis cosas y ya está.
00:08:08
Entonces, esto es este temita que hay ahora,
00:08:12
el de acceso a ficheros.
00:08:16
Entonces, ¿para qué nos va a servir este tema?
00:08:23
Primero, para conocer el acceso a ficheros básico, claro.
00:08:25
Y segundo, para usarlo, sobre todo,
00:08:29
que es la parte más interesante,
00:08:31
para usarlo para seguir practicando programación.
00:08:32
Para usarlo para seguir practicando lo que nos ocupa ahora,
00:08:36
que es aprender a programar y llegar a segundo programando,
00:08:39
bien, con soltura y sin perdernos
00:08:41
y sin cometer errores demasiado
00:08:43
horarios, ¿vale?
00:08:45
pues esto es lo que vamos a ver ahora
00:08:48
acceso a ficheros desde
00:08:49
mis aplicaciones Java
00:08:51
¿vale? el acceso a bases
00:08:52
de datos
00:08:55
lo dejamos así en gordote
00:08:56
para el curso que viene
00:08:59
vale, pues venga
00:09:01
bueno, pues ya sabéis que cualquier aplicación Java
00:09:06
es un montón de clases que hacen cosas
00:09:20
ya lo sabéis
00:09:22
o bien clases que ya están
00:09:23
en la JRE
00:09:25
y que yo uso, pues como la clase
00:09:28
Scanner que hemos usado, la clase
00:09:30
ArrayList, la clase
00:09:32
LinkedList, o bien clases que ya están y que yo
00:09:34
uso, o bien clases que me invento
00:09:36
yo, ¿vale? Pero en la gran mayoría
00:09:38
de las veces lo que hacemos es usar clases que ya están
00:09:40
hechas y esas clases me ofrecen
00:09:42
métodos para hacer cosas. Bueno,
00:09:44
pues eso es lo que vamos a hacer aquí.
00:09:46
Conocer las clases básicas
00:09:48
que ya están hechas
00:09:50
y que me permiten hacer cosas con
00:09:51
ficheros, escribir en ellos
00:09:54
leerlos, etc.
00:09:56
Todas esas clases que ya están hechas
00:09:57
pues de toda la vida
00:09:59
estaban en un
00:10:02
paquetito
00:10:05
que es Java.io que está
00:10:06
en la JRE, con lo cual no tenemos que
00:10:09
importarlo
00:10:11
y luego se incorporaron algunas
00:10:12
modificaciones, algunas
00:10:17
clases nuevas
00:10:19
en Java.io
00:10:20
para optimizar
00:10:23
el uso de las
00:10:24
clases de esta de aquí, pero vamos
00:10:27
esencialmente el funcionamiento es el mismo
00:10:29
y estas son las básicas
00:10:30
¿vale? pero bueno, vamos a mencionar un poquito
00:10:33
las clases
00:10:35
básicas de las dos son las que vamos a
00:10:36
mencionar y ya está, ¿vale? estos serían los dos
00:10:39
paquetes, para que nos pongamos
00:10:41
en contexto, que tienen las clases básicas
00:10:43
para acceder a ficheros, serían
00:10:45
estos dos, ¿vale?
00:10:47
bueno, pues un poquito por encima, ¿qué clases
00:10:51
hay ahí? ¿qué tenemos?
00:10:53
vale, pues si yo quiero trabajar
00:10:56
con un fichero
00:10:57
necesito
00:10:58
un objeto que me lo represente
00:11:00
porque en Java
00:11:02
todo lo que puede hacer lo tiene que hacer
00:11:03
con objetos, todo, es que no hay otra
00:11:06
lo tiene que hacer con objetos
00:11:08
bueno, pues si yo necesito un fichero que es mi primer
00:11:09
mi primer recurso
00:11:12
ajeno a la aplicación, trabajar con él
00:11:14
pues necesito un objeto Java
00:11:16
que me lo represente asociado a él
00:11:18
y yo trabajo con ese objeto Java
00:11:20
vale, pues ¿cuál es la clase Java
00:11:21
que representa
00:11:24
el objeto fichero?
00:11:30
File, la clase file de java.io es la clase java que representa un objeto fichero, entonces yo quiero trabajar con un fichero para pasárselo como parámetro a un método para que haga cosas con él, para hacer cosas con él, pues lo que suelo hacer es instanciar un objeto file asociado a ese fichero, ¿vale?
00:11:31
Asociado a ese ficherito
00:11:52
Y ahora ya la clase file
00:11:55
Este objeto que yo instancio
00:11:58
Asociado a este ficherito
00:11:59
Pues ya me ofrece
00:12:00
Un montón de métodos para hacer unas cuantas cosas
00:12:02
¿Vale? Pues por ejemplo
00:12:06
Ver si existe, ver que permisos tengo
00:12:09
Sobre él
00:12:11
En general me permite
00:12:12
Me ofrece a través de los métodos
00:12:14
Información sobre este fichero
00:12:17
Información, no todavía lecturas y escrituras
00:12:19
no, información sobre
00:12:22
el fichero, ¿vale?
00:12:24
cambiarle el nombre
00:12:25
borrarlo, cosas así
00:12:26
entonces esta es la clase
00:12:30
básica, en general
00:12:32
cuando un método o lo que sea necesita un fichero
00:12:34
para trabajar se le pasa en
00:12:36
objeto file, ¿vale?
00:12:37
el equivalente a este en java.new
00:12:42
sería el objeto
00:12:44
path, ¿vale? pero bueno
00:12:47
luego según vayamos viendo los ejemplos
00:12:50
pues lo iremos viendo
00:12:52
entonces los dos nombres
00:12:54
están bien escogidos
00:12:58
cada uno con su matiz
00:13:00
o sea este está bien escogido
00:13:01
porque representa un fichero
00:13:03
entonces pues mira file
00:13:06
representa un fichero y se llama file, que bien
00:13:07
pero este está bien escogido
00:13:09
también porque pone de manifiesto
00:13:11
lo que identifica un fichero
00:13:13
en realidad, a un fichero lo identifica
00:13:16
su nombre por supuesto
00:13:18
pero toda la ruta en la que está
00:13:20
del sistema de archivos, eso es lo que identifica
00:13:22
un archivo, su nombre y toda su
00:13:24
ruta
00:13:26
un recurso archivo
00:13:26
se identifica de forma única solamente
00:13:29
con toda su ruta además de su nombre
00:13:32
porque puede haber ficheros que se llaman
00:13:34
igual en rutas distintas
00:13:36
entonces la única forma de identificar de forma única un fichero
00:13:37
es toda su ruta con su nombre
00:13:40
y eso es lo que tenemos que saber
00:13:41
para instanciar el objeto file, etc
00:13:44
entonces quizá este nombre
00:13:45
es casi más bonito porque nos hace ver
00:13:47
que un fichero en realidad es toda una ruta
00:13:50
en mi sistema de archivo, no es un nombre
00:13:51
sin más, esto es una ruta
00:13:54
bueno, pues clase file, ¿qué más clases
00:13:55
vamos a ver? ahora antes de ponernos con los ejemplos
00:13:59
bueno, pues aparte de
00:14:02
instanciar un objeto archivo para tener información
00:14:03
sobre él, para pasárselo como parámetro
00:14:05
a un método, para que haga lo que sea, etc
00:14:07
nos interesa
00:14:09
leer y escribir en los
00:14:11
archivos, es esencialmente lo que nos interesa
00:14:13
vale
00:14:16
pues, vale, para
00:14:18
leer y escribir en un archivo
00:14:26
Java lo organiza mediante
00:14:28
flujos
00:14:31
¿vale? flujos o
00:14:32
en terminología Java Neo ya es más
00:14:36
canales, channels, pero bueno
00:14:38
es la misma idea, un stream
00:14:40
un channel, es la misma idea, es como hacer una pequeña
00:14:42
tubería hacia ese fichero
00:14:44
entonces
00:14:46
nuestra aplicación lo que hará será
00:14:49
leer de esa
00:14:52
tubería, pi pi pi, por aquí se van
00:14:54
enviando los bytes, por aquí van los bytes
00:14:56
y se va leyendo de esa tubería
00:14:58
entonces, ¿quién es capaz de leer
00:15:01
de esa tubería?
00:15:03
pues hay dos clases
00:15:06
asociadas a sacar información
00:15:07
de esa tubería o channel o canal básico
00:15:10
en javaío
00:15:12
estoy situada ahora, pero bueno
00:15:14
es más o menos la que se ha usado siempre
00:15:16
pues file input stream
00:15:18
sería directamente para sacar bytes
00:15:27
uno tras otro
00:15:32
y file reader
00:15:33
sería
00:15:39
para también sacar bytes
00:15:41
uno tras otro, pero
00:15:44
devolvermelos convertidos a char
00:15:46
interpretados como si fueran un char
00:15:48
entonces si yo sé que es un fichero de texto
00:15:49
directamente le asocio un file
00:15:51
reader, que me va a permitir ir sacando
00:15:54
los char tal cual
00:15:56
si yo no sé lo que hay ahí, que es un fichero
00:15:57
binario, pues le asocio un file
00:16:00
input string, y voy sacando los bytes
00:16:02
uno tras otro, a ver aquí estoy
00:16:04
en el bajo nivel completamente
00:16:07
estas son las clases de más bajo nivel que hay posibles
00:16:09
que me sacan directamente los bytes
00:16:11
luego claro
00:16:13
sobre esto
00:16:15
ya se pueden montar
00:16:16
clases más complejas para envolverme
00:16:19
en la complejidad y pues yo quiero
00:16:21
sé que tiene números enteros
00:16:23
pues léeme directamente enteros
00:16:25
entonces tendrá que leer 4 bytes
00:16:26
entonces sobre esto ya
00:16:28
hay clases
00:16:30
más complejas que se montan
00:16:32
para hacer cosas más sofisticadas
00:16:35
Pero que se apoyan sobre estas
00:16:37
Sobre las básicas
00:16:39
Que son estas dos
00:16:40
¿Vale?
00:16:41
Entonces si lo que yo quiero
00:16:44
Es en lugar de leer bytes
00:16:45
Escribir bytes
00:16:48
¿Vale? Pues las clases serían
00:16:49
Adiós
00:16:52
Serían file
00:16:56
Serían file output
00:16:57
Stream
00:17:03
O file writer
00:17:04
Bueno estas serían como las 5 básicas
00:17:07
Las de bajo nivel
00:17:12
Vamos a usarlas ahora
00:17:14
Antes de contar más historias
00:17:16
Vamos a usarlas ahora para hacer algún ejemplo
00:17:17
Y así pues seguimos programando
00:17:20
Un poquito y ya está
00:17:22
¿Vale? Antes de
00:17:24
Seguir hablando
00:17:26
Achar, claro
00:17:27
Coge los ceros y unos tal cual
00:17:42
Input es para
00:17:51
llevar de fichero a variable
00:17:52
y output es
00:17:55
para llevar de variable a fichero
00:17:57
¿vale?
00:17:59
vamos a verlo ahora
00:18:01
en un ejemplo
00:18:03
los de DAO sueñan mucho por las noches
00:18:05
no les hagan ni caso
00:18:24
obviamente
00:18:27
después de semana santa habrá un examen
00:18:34
pero no sabemos si dos días después o tres meses después
00:18:36
O sea, lo que han dicho
00:18:38
Estrictamente falso no es
00:18:41
Pero vamos, que no tenemos en mente
00:18:43
Ningún examen todavía, más allá de cuando
00:18:49
Tengo que hacer un examen, porque en mayo hay que hacer exámenes
00:18:51
Claro
00:18:53
Pero es que realmente, tampoco puede ser mucho después
00:18:54
Porque es que tenemos un
00:18:57
Problemón
00:18:59
Los ficheros
00:19:00
Ejemplos
00:19:05
Vale
00:19:08
No
00:19:09
Porque volvemos de Semana Santa
00:19:14
pues el 6 de abril
00:19:19
puede ser, el 7 de abril
00:19:22
el 7 de abril
00:19:24
y
00:19:30
la
00:19:31
evaluación vuestra
00:19:33
es el 18 de mayo
00:19:36
con lo cual
00:19:38
del 11
00:19:40
entonces tenemos un mes
00:19:42
vale, pues venga
00:19:44
Este porque se me pone
00:19:50
Vale
00:19:54
Pues venga
00:20:01
Vamos a hacernos un paquete
00:20:03
Por aquí
00:20:05
Primero para trabajar
00:20:08
Ejemplo con texto
00:20:10
Que es la forma
00:20:13
La forma más fácil de
00:20:14
Entenderlo de buenas a primeras
00:20:17
Venga, contexto
00:20:19
Pues ahora vamos a hacernos
00:20:22
Un programita
00:20:24
¿Por qué no me aparece
00:20:26
Aquí lo de
00:20:40
Ah, es que
00:20:41
Me parece bien pequeñito
00:20:43
Vale, pues venga
00:20:48
Pues venga, por ejemplo
00:21:07
Vamos a hacer una
00:21:11
minimísima aplicación
00:21:13
que trabaja con nombres
00:21:16
de personas
00:21:17
entonces esos nombres de personas
00:21:18
para trabajar con ellos tendrían que estar
00:21:22
guardados en algún sitio
00:21:23
pues vamos a guardarlos por ejemplo aquí
00:21:24
en una lista
00:21:27
vale
00:21:30
vale
00:22:04
pues a ver
00:22:09
vamos a hacer un bucle
00:22:09
que le ha
00:22:16
solicite nombres y los guarde
00:22:18
luego al final, antes de irse, los guarde en el fichero
00:22:20
vale
00:22:23
pues yo tengo aquí mi nombre
00:22:23
y ahora
00:23:05
a nombres.add
00:23:07
scan.nextline
00:23:10
vale, pues aquí
00:23:15
nosotros ya podemos procesar
00:23:24
los nombres, hacer lo que sea
00:23:26
lo que sea que mi aplicación
00:23:29
hiciera con esos nombres
00:23:33
lo que fuera
00:23:34
pero antes de irme, yo ya de mi aplicación
00:23:35
Antes de procesar los nombres
00:23:44
Yo los
00:23:46
Vale
00:23:48
Los quiero dejar
00:23:52
Vale, los quiero dejar guardados
00:23:53
En un fichero
00:23:59
Venga, pues me voy a hacer ahora aquí un método
00:23:59
Guardar nombres
00:24:05
Al que le
00:24:07
No hace falta que le pase
00:24:09
Mis nombres, porque como están como variable local
00:24:11
Vale, guardar nombres
00:24:13
Venga, vamos a hacernos este método
00:24:16
Bueno
00:24:18
Pues proceso para guardar en un fichero
00:24:33
Proceso para guardar en un fichero
00:24:36
Primero
00:24:39
Abrir el fichero
00:24:40
Para escritura
00:24:45
Para escritura
00:24:46
Después de que lo hayamos abierto
00:24:49
Haremos las escrituras
00:24:53
Escribimos
00:24:56
Y después de que hemos escrito
00:24:57
Cerramos
00:25:02
¿Vale?
00:25:03
Estos son los tres pasos
00:25:05
Abrimos el fichero, escribimos y cerramos
00:25:09
Vale
00:25:12
Abrir el fichero
00:25:13
¿Qué significa?
00:25:16
Instanciar el objeto que corresponda
00:25:18
Para
00:25:20
Abrir un fichero para leer de él
00:25:22
Entonces
00:25:24
En este caso
00:25:26
Mi fichero va a ser de texto
00:25:28
Porque yo voy a guardar caracteres que luego quiero leer como texto
00:25:29
Entonces para leer
00:25:32
Tendríamos dos alternativas
00:25:34
Estando a nivel básico
00:25:35
El más básico posible
00:25:38
El más tocando el bajo nivel
00:25:39
File input, perdón
00:25:41
Para escritura
00:25:43
File output stream
00:25:45
Output es salir, salgo del fichero
00:25:46
O sea, perdón, salgo de la aplicación
00:25:49
Output significa salgo de la aplicación
00:25:51
De mi aplicación me voy fuera
00:25:53
Pues file output stream
00:25:55
Para mandar bytes tal cual
00:25:57
O file writer
00:26:00
Que sería en mi caso el que aplicaría
00:26:02
Porque estoy escribiendo cosas que son caracteres
00:26:05
Entonces, opciones que tenemos a nivel básico tendríamos, repito, esta para escribir bytes sin más, o sea, bytes, y esta otra que he dicho, escribir caracteres.
00:26:07
En nuestro caso es lo que queremos, pues entonces toca instanciar este objeto, que este es el que toca, toca este.
00:26:37
vale, siempre lo mismo, abrimos el fichero
00:26:43
escribimos o leemos
00:26:47
si estuviéramos en lectura y cerramos
00:26:49
vale, y abrir significa
00:26:50
instanciar el objeto
00:26:53
que toque, pues para escribir
00:26:55
en un fichero de caracteres
00:26:58
FileWriter, para escribir bytes
00:26:59
sin más, sin interpretar
00:27:02
la información, FileOutputStream
00:27:04
en este caso caracteres
00:27:05
vamos a instanciarlo
00:27:07
FileWriter, vale
00:27:08
como instanciamos un objeto
00:27:13
normalmente con el
00:27:17
constructor, a menos que tengamos
00:27:19
un
00:27:22
método que llame al
00:27:22
constructor, en este caso con el constructor
00:27:25
vale, y ahora
00:27:27
a FileWriter, ¿qué hay que pasarle al
00:27:29
constructor? hay que pasarle
00:27:31
el fichero en el
00:27:33
que vamos a escribir, eso es lo que hay que pasarle
00:27:35
hay que pasarle el fichero en el que vamos a escribir
00:27:37
porque este objeto FileWriter
00:27:39
se asociará a un fichero
00:27:41
este FileWriter será como ese flujo
00:27:43
ese canal
00:27:45
Entonces ahí hay que pasar el fichero
00:27:47
Se puede pasar de dos maneras
00:27:49
El nombre del fichero sin más
00:27:52
Con toda su ruta, por supuesto
00:27:54
Es decir, un string
00:27:56
O el objeto file que lo representa
00:27:57
El constructor está sobrecargado
00:27:59
Entonces, por ejemplo
00:28:03
Vamos a preguntar aquí
00:28:04
En qué fichero quiere guardarlo
00:28:09
En qué fichero quiere guardar
00:28:11
ahora aquí nos dirá el nombre del fichero
00:28:20
me voy a coger el escáner de arriba
00:28:29
aquí estoy
00:28:42
vale, este es el nombre del fichero
00:28:48
en el que quiere guardar
00:28:55
vale, entonces
00:28:57
yo puedo pasar el nombre del fichero
00:28:58
directamente aquí
00:29:01
si quiero
00:29:03
vale
00:29:04
puedo pasar directamente el nombre del fichero
00:29:05
y ya está
00:29:08
este flujo se asociará a ese fichero
00:29:09
ya se quedaría abierto
00:29:12
se quedaría abierto
00:29:13
cuidado
00:29:14
si esto es el nombre del fichero sin más
00:29:16
recordad que un recurso fichero
00:29:19
no se queda identificado por su nombre
00:29:21
no, así se queda ambiguo
00:29:23
porque puede llamarse un fichero igual
00:29:25
en muchos sitios de mi sistema de archivos
00:29:27
entonces si yo paso el nombre
00:29:29
sin más
00:29:31
lo que asume la clase
00:29:32
FileWriter es que entonces
00:29:34
la ruta en la que está
00:29:36
ese fichero, la ruta es
00:29:39
la raíz del proyecto
00:29:41
es decir, esto
00:29:42
¿vale? si yo paso aquí el nombre sin más
00:29:44
él asume que entonces la ruta
00:29:49
es la de la raíz
00:29:51
del proyecto, esa es la ruta que se llama
00:29:52
por defecto de cualquier aplicación Java
00:29:54
la ruta raíz de la cual
00:29:56
cuelgan todos los paquetes
00:29:58
¿vale? entonces yo puedo hacer
00:30:00
ahora mismo mi método
00:30:04
así, pasando directamente el nombre
00:30:05
y ya está, veréis que el fichero
00:30:07
me aparece aquí
00:30:09
me aparece ahí en esa ruta
00:30:11
Que yo no quiero que sea esa ruta
00:30:13
Sino otra
00:30:16
Pues le tengo que pasar aquí
00:30:17
El string con toda la ruta
00:30:19
Enterita, toda
00:30:22
El c, dos puntos, barra, etc
00:30:23
¿Vale?
00:30:25
Esa es una ruta absoluta
00:30:27
¿Es obligatorio que yo pase siempre rutas absolutas?
00:30:29
No, no eso no es obligatorio
00:30:33
Si es que ni siquiera es deseable
00:30:34
Porque una aplicación
00:30:36
Que está basada en rutas absolutas
00:30:38
Que tú cuando
00:30:40
en esa aplicación haces accesos
00:30:41
a fichas de frutas absolutas, es muy poco
00:30:43
portable, lógicamente
00:30:45
porque yo puedo poner aquí
00:30:47
C, dos puntos, uses, Raquel, bla bla bla
00:30:48
y ahora te doy mi aplicación
00:30:51
para que tú la ejecutes en tu equipo
00:30:53
cuando esa aplicación intente abrir
00:30:55
el recurso C, uses, Raquel
00:30:57
va a decir esta ruta aquí no existe
00:30:59
entonces no es
00:31:01
de hecho es absolutamente desaconsejable
00:31:02
jamás lo hacemos lógicamente
00:31:06
usar rutas
00:31:07
absolutas para identificar
00:31:09
ubicaciones de ficheros
00:31:11
porque esa ruta va a perder validez
00:31:13
en cuanto tú muevas la aplicación
00:31:16
a otro equipo
00:31:17
entonces, ¿qué es lo que podemos
00:31:18
poner? rutas relativas
00:31:21
relativas a
00:31:24
cual a este
00:31:26
rutas relativas, entonces si yo pongo
00:31:26
por ejemplo
00:31:29
carpeta
00:31:30
hola barra nombre del fichero
00:31:36
pues la carpeta hola se sobreentiende
00:31:38
que está aquí dentro, es una ruta
00:31:40
relativa, si yo hago ahora el
00:31:42
dos puntos, recordáis que con dos puntos
00:31:44
te subes un
00:31:46
piso por encima del sistema de archivos
00:31:47
¿verdad? vale, pues si yo pongo
00:31:49
la ruta dos puntos, barra, no sé
00:31:52
qué, pues me he subido por
00:31:54
encima de mi ruta
00:31:56
por defecto que es esta
00:31:58
y ahí ya me he ido a la carpeta, entonces siempre puedo
00:32:00
hacer rutas relativas
00:32:02
a esta, ¿vale?
00:32:04
Que es lo deseable, rutas relativas a esta
00:32:06
Y esas ya sí que van a funcionar
00:32:08
Pase yo mi aplicación a donde la pase
00:32:11
¿Vale?
00:32:13
Y siempre deberían tener rutas relativas
00:32:15
Claro
00:32:17
Bueno, aquí nosotros, como vamos a pasar el nombre sin más
00:32:17
Pues eso significa
00:32:20
Que mi fichero va a aparecer aquí
00:32:23
¿Vale? Estupendo
00:32:24
Bueno, pues
00:32:25
Yo puedo pasar aquí el nombre sin más
00:32:28
Pero este constructor
00:32:30
También permite que yo le pase
00:32:32
el objeto file asociado
00:32:35
a este
00:32:37
¿vale? pero bueno, con el objeto file
00:32:37
lo ponemos
00:32:41
como ejemplo ahora en otro método
00:32:43
bueno, pues ya está, esto ya está
00:32:44
se me ha aparecido en rojo, ¿por qué?
00:32:47
porque
00:32:50
FileWriter puede lanzarme
00:32:50
una excepción y esta sí que no es
00:32:53
runtime excepción, esta es una excepción
00:32:55
de verdad
00:32:57
¿vale? si nosotros entramos en la clase
00:32:58
FileWriter, ¿veis?
00:33:01
tiene un
00:33:08
throws io exception
00:33:10
es decir
00:33:12
puede que yo me encuentre un problema
00:33:14
de entrada y salida cuando trato de instanciar
00:33:16
el flujo, puede que yo me
00:33:18
encuentre io exception
00:33:20
si entráramos en ella
00:33:22
bueno, esto
00:33:23
me va a tardar
00:33:28
veré que hereda de exception
00:33:33
no de runtime exception, pero no me la
00:33:38
no me llega a abrir la
00:33:40
jerarquía esta
00:33:45
¿cuál es la diferencia?
00:33:47
bueno, la que hemos visto
00:33:52
en las clases anteriores
00:33:56
si una excepción hereda de excepción
00:33:57
eso implica
00:34:00
que es como de mayor rango
00:34:02
y es automáticamente de obligada
00:34:03
captura o propagación
00:34:06
donde tú la llames
00:34:07
bueno, tú la has decidido
00:34:08
por programa
00:34:11
entonces, se supone que son excepciones
00:34:12
que es más
00:34:15
peligroso que te aparezcan en tiempo de ejecución
00:34:17
entonces ya desde tiempo de compilación
00:34:20
obligas al que desarrolla el código
00:34:22
a pronunciarse sobre si te sale
00:34:24
¿vale? entonces es una cuestión de diseño
00:34:26
de categoría de excepciones que yo no quiero
00:34:28
dejar, no quiero arriesgarme
00:34:30
a que aparezcan en tiempo de ejecución
00:34:33
porque sí ¿vale?
00:34:34
entonces las que tú haces que hereden de exception
00:34:36
o las que están hechas
00:34:38
que hereden de exception, la máquina virtual
00:34:40
como esta, la de
00:34:42
io exception, se supone que esa es
00:34:44
lo suficientemente, porque claro
00:34:46
si tú cuentas que tu aplicación va a abrir un fichero
00:34:48
y luego no puede abrirlo
00:34:50
pues te la has cargado entera
00:34:51
entonces tiene sentido que ya de partida
00:34:53
cuando yo hago aquí
00:34:56
esto
00:34:57
me diga
00:34:59
ojo, que esto puede que te encuentres
00:35:02
un problema, que este fichero no lo pueda
00:35:04
abrir porque tengo que hacer el tema de archivos
00:35:06
dime que hago si no
00:35:07
entonces ya directamente
00:35:08
tú ya dices, pues hago un try catch
00:35:12
y ya doy una alternativa
00:35:14
¿vale?
00:35:16
Array in this auto bound exception
00:35:17
esa no hereda de excepto, hereda de runtime
00:35:19
entonces esa no tenemos que
00:35:22
capturarla todo el rato, ¿por qué? porque asumimos
00:35:24
que esa excepción no va a salir
00:35:26
porque si sale es porque has hecho el código fatal
00:35:28
entonces vale, que te salga y lo arreglas
00:35:30
pero esta no es que no depende del programador
00:35:32
esta te puede salir por un problema
00:35:34
ajeno al programador, entonces
00:35:36
te avisa desde ya
00:35:37
para que digas, oye, si pasa esto que no es
00:35:39
tu culpa, pero podría ocurrir, ¿qué haces?
00:35:42
y tú como programador lo arreglas, ¿vale?
00:35:44
bueno, pues entonces
00:35:51
aquí efectivamente me dice, oye, cuidado
00:35:52
que te podría salir un io exception
00:35:54
porque yo no te prometo
00:35:56
que el fichero esté disponible
00:35:58
o
00:36:01
¿qué haríamos si no? ¿qué haríamos?
00:36:01
Bueno, pues recordad que cuando
00:36:04
tú tienes el aviso de que hay
00:36:06
una excepción que te puede salir, tienes dos opciones
00:36:08
la
00:36:10
fea y la bonita
00:36:12
la bonita
00:36:15
es capturar y decir, voy a
00:36:16
dar yo una solución
00:36:18
¿vale? voy a dar yo una solución
00:36:19
Capturar, ya sabemos que es esta
00:36:22
¿Vale?
00:36:25
Entonces, si no puedo instanciar el objeto
00:36:27
Si no puedo instanciarlo
00:36:30
Pues aquí digo lo que sea
00:36:32
O digo, elige otro nombre de fichero
00:36:34
Lo que sea
00:36:37
Ya lo que yo decida
00:36:38
Error al acceder al archivo
00:36:40
Se usará uno por defecto
00:36:48
Lo que sea, lo que yo decida
00:36:51
pero ya sé que mi aplicación no para
00:36:53
que eso es lo bueno, mi aplicación no va a parar
00:37:01
¿vale? ya sé que mi aplicación no va a parar
00:37:03
mi aplicación seguirá por aquí
00:37:05
en función
00:37:08
de lo que yo siga haciendo
00:37:10
me habré creado un archivo por defecto, lo que yo quiera
00:37:11
vamos, lo que yo quiera
00:37:13
¿cuál era la opción mala?
00:37:14
la opción mala
00:37:21
depende de donde esté yo, claro
00:37:22
uy
00:37:23
pues estoy programando en plan rápido
00:37:24
estoy en una aplicación, quiero hacer pruebas cuanto antes
00:37:30
no quiero que me quede un código muy engorroso
00:37:32
tengo la seguridad de que no va a haber ningún problema
00:37:34
con mi sistema de archivos
00:37:36
pues la es
00:37:37
pues propago, de las dos opciones que tengo
00:37:39
que son
00:37:42
o capturar con el
00:37:43
try catch o propagar
00:37:46
pues propagar
00:37:48
y propagar que significa
00:37:49
pues propagar significa en el método
00:37:51
donde esa excepción puede salir
00:37:54
en el método donde puede salir
00:37:57
sea el que sea
00:37:58
avisas
00:37:59
vale
00:38:01
entonces
00:38:03
esta puede ser fea
00:38:09
como digo yo, no, depende
00:38:12
en este caso no es tan fea porque
00:38:14
el mes
00:38:16
lo que haría no sería parar el programa
00:38:18
sino el aviso
00:38:21
propagarlo para que lo dé este
00:38:22
entonces el aviso ahora ya salta y se queda
00:38:24
aquí, entonces todavía
00:38:27
me queda una oportunidad de try catch
00:38:28
todavía me queda una oportunidad de try catch que es aquí arriba
00:38:30
entonces aquí todavía
00:38:33
no he actuado tan mal
00:38:34
no he actuado tan mal
00:38:36
porque lo que he dicho es, oye, cuidado
00:38:38
que puede que salga un error
00:38:40
como yo no soy
00:38:42
el programa principal
00:38:44
todavía, como yo no soy el programa principal
00:38:47
aviso arriba
00:38:49
propago con el
00:38:51
el aviso llega aquí
00:38:53
y aquí todavía
00:38:55
tengo una oportunidad de try catch
00:38:57
¿vale? para decir, oye
00:38:59
no se ha podido guardar nombres
00:39:01
Bueno, pues aquí todavía tengo una oportunidad de try-catch
00:39:02
Y aquí ya sí que haría
00:39:05
No se han
00:39:08
Podido
00:39:18
Guardar
00:39:19
Y al menos el que ha trabajado
00:39:20
Con estos nombres sabe que los ha perdido
00:39:23
O si no
00:39:25
Se puede meter en un bucle
00:39:27
Y lo que sea, lo que uno decida
00:39:29
¿Vale?
00:39:31
Aquí lo que sí que sería feo
00:39:42
Es aquí seguir propagando
00:39:44
Porque aquí ya tengo el main
00:39:46
vale, entonces
00:39:47
si aquí yo
00:39:49
ante este aviso
00:39:53
de guardar nombres
00:39:56
de cuidado, que puede salir una excepción
00:39:58
vale
00:39:59
ante este aviso
00:40:02
yo dijera, bueno, voy a
00:40:03
seguir pasando el aviso hacia arriba
00:40:06
porque tengo dos opciones, o ahora ya
00:40:07
capturo o lo sigo pasando hacia arriba
00:40:09
pues si yo opto por no
00:40:11
emborronar el código y porque no me quede feo
00:40:13
opto por, venga, pues vamos
00:40:15
para arriba, ahora
00:40:17
haya el Throws, ¿quién lo está
00:40:19
lanzando? El Main.
00:40:21
Y esto ya sí que no.
00:40:23
A menos que esté todavía en fase de pruebas,
00:40:25
haciendo mis cosas. Esto ya sí que no.
00:40:27
Porque cuando es el Main
00:40:29
el que tiene el Throws, cuando
00:40:31
la excepción llega, ¿qué ocurre?
00:40:33
El programa se para. Porque el Main ya no tiene
00:40:35
nadie a quien delegar
00:40:37
y seguirle. El Main ya no tiene nadie.
00:40:39
Es el método
00:40:42
raíz. Entonces, si yo propago
00:40:43
y le digo, oye, guardar nombres,
00:40:45
si te da un error,
00:40:47
propaga, el main dice
00:40:49
uy, pues yo soy el último
00:40:51
yo soy el último, no puedo propagárselo a nadie
00:40:52
para que el de arriba decida si try catch o no
00:40:55
yo soy el último, pues programa se para
00:40:57
entonces que el main tenga un
00:40:59
throws o
00:41:01
cualquier clase principal
00:41:02
pues hombre, ahí ya sí que
00:41:04
cuando estamos todavía
00:41:07
en fase de desarrollo vale, porque no tengo
00:41:09
tantos try catch, pero no debería
00:41:11
¿y lo mejor es hacer el try catch cuando
00:41:13
cuando primero aparece?
00:41:15
es que depende, depende de
00:41:17
si lo que yo estoy haciendo es un paquete
00:41:19
depende del diseño que haga
00:41:21
vale, pues entonces este throws
00:41:22
aquí sí que no nos gusta
00:41:26
nada, y aquí ya
00:41:28
sí que lo pondríamos, intenta
00:41:34
guardar, dejo
00:41:36
el print extract trace porque estoy todavía
00:41:40
en fase de desarrollo, pues para que
00:41:41
me dé datos técnicos
00:41:44
bueno, pues la excepción la tenemos
00:41:47
ya resuelta, la excepción la tenemos
00:41:55
resuelta, ya hemos podido
00:41:59
crear nuestro flujo
00:42:01
y ahora ya
00:42:02
este flujo nos permite escribir
00:42:04
¿vale? ahora ya se trata
00:42:06
de ver qué métodos me ofrece
00:42:09
y cuál me interesa, ya está, cuál me interesa
00:42:10
¿qué métodos me ofrece?
00:42:13
pues un montón
00:42:14
si vemos ahí lo que nos ofrece, pues un montón de cosas
00:42:15
pues nos ofrece
00:42:22
un montón de métodos, ¿vale?
00:42:31
el file writer
00:42:33
en particular relacionado con
00:42:34
escritura, los write, pues puedes
00:42:37
mandar un array de chat de golpe
00:42:39
Puedes mandar un string de golpe
00:42:41
¿Vale?
00:42:44
Puedes mandar
00:42:46
Esto lo entenderemos mejor
00:42:47
Cuando veamos la lectura
00:42:50
Esto no significa que has mandado un número entero
00:42:51
No, tú le mandas una variable entera
00:42:53
Y él lo que guarda es el último byte
00:42:55
De los cuatro, el menos significativo
00:42:58
Porque interpreta
00:43:00
Que ahí es donde está el char
00:43:02
¿Vale?
00:43:03
¿Por qué de esta manera tan extraña?
00:43:05
En lugar de un solo char
00:43:07
Para luego poder sincronizarse con el de leer
00:43:08
Luego con la lectura lo veremos
00:43:10
¿Vale? Pero no significa que puedas guardar un número
00:43:12
No, es un único char, lo que guardas es que está en el byte menos significativo
00:43:14
Entonces, pues hombre
00:43:17
Este parece bastante útil
00:43:18
Con este puedes mandar un string enterito
00:43:20
Pues venga, vamos a
00:43:21
A usar este
00:43:24
¿Vale?
00:43:26
Vamos a usar este, pero vamos a tener que hacer un bucle
00:43:28
Para poder escribir todos
00:43:30
Pues venga
00:43:32
Para cada
00:43:34
Nombre
00:43:35
En
00:43:39
nombres
00:43:41
para cada nombre
00:43:43
nombres, ala, escribe
00:43:49
escribir un fichero
00:43:52
de texto, pues lo más fácil del mundo
00:43:54
vale, esto ya está
00:43:56
cada write
00:44:01
cada ejecución de write
00:44:02
escribe y deja posicionado
00:44:05
el fichero internamente para que los siguientes
00:44:07
se escriban abajo, claro, no se lo escribe todo el rato
00:44:09
¿qué parámetro?
00:44:11
no, porque es n
00:44:15
¿lo pw era?
00:44:17
era este objeto
00:44:21
que acabo de crear
00:44:23
entonces
00:44:24
inicialmente
00:44:29
a ver, este constructor
00:44:33
tiene un segundo parámetro
00:44:34
que yo puedo usar o no
00:44:36
que es
00:44:39
si yo quiero añadir
00:44:40
en el fichero por si yo hubiera algo antes
00:44:42
porque puede ser que ese fichero
00:44:45
que yo abro para escribir
00:44:46
ya tenga algo de antes
00:44:48
pues puede ser que yo quiera añadir
00:44:49
o eliminar todo lo que hubiera y hacerlo de nuevas
00:44:52
entonces este parámetro de aquí
00:44:54
este segundo parámetro del constructor
00:44:57
es un boolean
00:45:00
que yo lo puedo usar
00:45:01
si lo pongo a true
00:45:03
significa que lo quiero en modo añadir
00:45:04
vale
00:45:07
entonces vamos a ponerlo ahí
00:45:08
el segundo parámetro del constructor
00:45:11
me indica
00:45:15
si quiero
00:45:20
añadir o borrar
00:45:21
si no pones nada por defecto es
00:45:24
falso, te lo haría
00:45:30
de limpio el fichero, te sobreescribiría
00:45:32
o sea, te borraría
00:45:34
todo lo anterior y lo empezaría de cero
00:45:36
se atrúes para
00:45:37
añadir
00:45:39
eso
00:45:41
lo que hubiera
00:45:42
previamente, vale, vamos a
00:45:45
poner lo que añada y ya está
00:45:50
vale, una vez que ya hemos
00:45:51
escrito
00:45:56
hay que cerrar el flujo
00:45:57
si no lo cerramos
00:46:00
cuando el programa acabe se va a cerrar igualmente
00:46:02
pero si el programa no termina
00:46:05
porque hace más cosas y yo no lo cierro
00:46:07
el fichero se queda bloqueado
00:46:08
y si algún otro proceso quisiera trabajar con él
00:46:11
pues no podría
00:46:13
entonces siempre hay que cerrar los flujos
00:46:13
que se abren, claro
00:46:17
pues ya está, vamos a probarlo rápidamente
00:46:18
y paramos, a ver si hemos hecho algo mal
00:46:30
¿eh?
00:46:32
lo que hubiera de antes
00:46:41
Lo borra enterito
00:46:42
No es que sobreescriba
00:46:44
Porque podríamos interpretar que si el de antes tiene algo más
00:46:46
Lo de abajo se queda sin sobreescribir
00:46:49
No, no, no, no, lo limpia todo de cero
00:46:50
Y añade lo que tú
00:46:52
Hayas puesto
00:46:54
¿Eh?
00:46:56
Un segundo abajo
00:46:57
Eh
00:46:58
Cada nombre lo va mandando
00:47:00
Vale, pues venga
00:47:07
Aquí me está pidiendo los nombres
00:47:12
Los 10 nombres que yo le he puesto
00:47:14
Vale, ¿en qué fichero
00:47:16
Quiere guardarlo?
00:47:23
Le voy a dar un nombre cualquiera
00:47:25
Porque si no existe, lo va a crear
00:47:27
¿Y dónde?
00:47:28
Como no le hemos dado ruta en la raíz del proyecto
00:47:30
Pues en el fichero
00:47:33
Nombres.txt
00:47:35
Por ejemplo
00:47:37
Terminado
00:47:38
Vale, no ha salido de exception
00:47:40
Entonces si refrescamos aquí el proyecto
00:47:42
Si lo refrescamos
00:47:45
Pues aquí ha aparecido
00:47:48
Y aquí están los nombres
00:47:49
¿Vale?
00:47:52
Como lo he abierto
00:47:57
Si lo haces a refrescar para que te aparezca todo
00:47:58
Claro, yo no he puesto saltos de línea
00:48:00
Entre ellos, pues los ha puesto todos seguidos
00:48:03
Esto, claro, habría sido
00:48:04
Más bonito
00:48:07
Porque así nos ha quedado muy feo
00:48:07
Lógicamente
00:48:10
Habiendo escrito
00:48:12
Write más
00:48:15
El barra n
00:48:16
Claro
00:48:20
Le voy a quitar para que no añade
00:48:25
Y me lo haga de limpias otra vez
00:48:27
Vale, ahora ya me los va a poner
00:48:29
Con salto de línea
00:48:35
Nombres.txt
00:48:36
Por ejemplo
00:48:46
Ahora ya sí
00:48:47
Vale, vamos a parar aquí un segundinín
00:48:52
- Materias:
- Programación
- Niveles educativos:
- ▼ Mostrar / ocultar niveles
- Formación Profesional
- Ciclo formativo de grado superior
- Primer Curso
- Subido por:
- Raquel G.
- Licencia:
- Todos los derechos reservados
- Visualizaciones:
- 4
- Fecha:
- 17 de marzo de 2026 - 12:27
- Visibilidad:
- Clave
- Centro:
- IES ROSA CHACEL
- Duración:
- 48′ 59″
- Relación de aspecto:
- 1.78:1
- Resolución:
- 1920x1080 píxeles
- Tamaño:
- 945.12 MBytes