1 00:00:00,000 --> 00:00:05,719 Voy a grabar esta clase, por lo tanto, si habláis, me dais consentimiento para que grabe esta voz. 2 00:00:06,240 --> 00:00:13,660 Entonces, ayer empezamos, bueno, antes de ayer, hace unos días, empezamos con la persistencia de datos 3 00:00:13,660 --> 00:00:16,820 y vimos la posibilidad de escribir en ficheros, ¿vale? 4 00:00:16,859 --> 00:00:21,620 Ayer lo que empezamos es cómo puedo guardar un objeto, ¿vale? 5 00:00:22,239 --> 00:00:27,600 Hasta antes, nosotros simplemente utilizamos o byte o carácter, 6 00:00:27,600 --> 00:00:35,320 si trabajamos con texto, para grabar en un fichero o leer desde un fichero, línea por línea o carácter por carácter, byte por byte, 7 00:00:35,479 --> 00:00:39,939 esto depende de las necesidades y de las exigencias que tengo en un determinado momento. 8 00:00:41,020 --> 00:00:45,979 Sin embargo, sería útil, puesto que nosotros programamos orientado a objetos, guardar objetos. 9 00:00:46,460 --> 00:00:55,780 Entonces, ayer hicimos un primer intento de esto, que es simplemente guardar los objetos como texto. 10 00:00:55,780 --> 00:01:00,320 entonces nosotros en alumnos nos inventamos un metodito 11 00:01:00,320 --> 00:01:04,680 que lo que hacía era representar los valores de este objeto 12 00:01:04,680 --> 00:01:08,319 por ejemplo separados por un carácter especial 13 00:01:08,319 --> 00:01:10,359 en nuestro caso eran dos puntos 14 00:01:10,359 --> 00:01:13,420 entonces cuando yo quería guardar el objeto 15 00:01:13,420 --> 00:01:15,840 lo que hacía es no guardar el objeto 16 00:01:15,840 --> 00:01:19,379 sino guardar los valores de los atributos de este objeto 17 00:01:19,379 --> 00:01:22,760 este es un método muy sencillo 18 00:01:22,760 --> 00:01:26,159 muy poco práctico y muy poco eficiente 19 00:01:26,159 --> 00:01:30,299 que se puede utilizar cuando los objetos que utilizo 20 00:01:30,299 --> 00:01:33,900 son muy muy sencillos, como era el caso de nuestro alumno 21 00:01:33,900 --> 00:01:38,280 que solo tenía valores, digamos, básicos 22 00:01:38,280 --> 00:01:42,239 es verdad que string es un objeto, pero es verdad también que nosotros 23 00:01:42,239 --> 00:01:45,180 lo hemos siempre casi utilizado como un tipo primitivo 24 00:01:45,180 --> 00:01:50,239 el problema de este método es que se complica mucho a la hora 25 00:01:50,239 --> 00:01:54,060 de utilizar objetos que contienen otros objetos dentro, ¿vale? 26 00:01:54,060 --> 00:01:58,760 Porque cuando estamos trabajando con las referencias, ya esto se complica. 27 00:01:58,900 --> 00:02:05,140 Si imaginamos el alumno que tenga asignado un profesor y luego tenga varios alumnos 28 00:02:05,140 --> 00:02:12,539 que tiene que apuntar al mismo profesor, pues esta cosa hecha con el método de guardar los objetos 29 00:02:12,539 --> 00:02:17,979 directamente como cadenas de caracteres al fin y al cabo, se puede complicar 30 00:02:17,979 --> 00:02:31,719 Porque cuando recrearé ese profesor, cuando creo ese objeto profesor, tengo que acordarme que no lo tengo que recrear por cada alumno, sino lo tengo que crear una vez sola y cada alumno tendrá que apuntar al mismo objeto recreado, ¿vale? 31 00:02:31,719 --> 00:02:59,379 Entonces, ¿se puede hacer? Sí se puede hacer, pero se complica mucho la gestión. Tengo que conocer muy bien dónde están los puntos críticos de mi aplicación para que cuando, por ejemplo, recargue mi aplicación, en este ejemplo que estamos haciendo, tendría más sentido crear antes todos los profesores y una vez que he creado todos los profesores empezar a crear los alumnos porque así tengo ya los profesores creados y si hay tres alumnos que apuntan al mismo profesor ya tengo el objeto. 32 00:02:59,379 --> 00:03:04,740 le puedo decir, mira, oye, directamente este es el objeto al que te refieres, ¿sí? 33 00:03:05,080 --> 00:03:12,539 Esto porque, ¿sabéis qué? Si cada alumno tuviera su propio profesor y modificara algo del profesor 34 00:03:12,539 --> 00:03:17,379 o se modificara algo de ese profesor, pues solo se reflejaría en ese alumno, ¿vale? 35 00:03:17,400 --> 00:03:22,379 Porque hay instancias distintas. Pero si el profesor es único y de repente cambia el horario de atención, 36 00:03:23,139 --> 00:03:27,759 qué sé yo, de tutoría, pues se debería reflejar en todos sus alumnos. 37 00:03:27,759 --> 00:03:36,960 Entonces debería ser una instancia única, compartida como referencia por todos los alumnos. Estas son cosas de programación básica. 38 00:03:37,219 --> 00:03:50,659 Si en vez es como teníamos nosotros, que sostancialmente teníamos datos que son propios del alumno y no se comparten con ningún otro alumno, el nombre del alumno no lo compartiré entre varios alumnos, 39 00:03:50,659 --> 00:04:22,339 Pues entonces sí que se puede hacer como hemos hecho ayer. Ayer hicimos un botón para guardar. Este botón de aquí, que sostancialmente tenía, cuando lo pinchaba, lo que hacía era crearse un printwriter y recorría a los alumnos. 40 00:04:22,339 --> 00:04:24,199 y por cada alumno 41 00:04:24,199 --> 00:04:25,980 encontrado en todos los alumnos 42 00:04:25,980 --> 00:04:27,639 lo que hacía era escribirlo 43 00:04:27,639 --> 00:04:29,759 en el fichero con el programita 44 00:04:29,759 --> 00:04:32,139 uno por línea, con el método 45 00:04:32,139 --> 00:04:34,160 y sostancialmente lo que 46 00:04:34,160 --> 00:04:35,480 hacía era escribir 47 00:04:35,480 --> 00:04:37,800 un pequeño 48 00:04:37,800 --> 00:04:38,680 fichero 49 00:04:38,680 --> 00:04:41,920 que lo tenemos por aquí 50 00:04:41,920 --> 00:04:44,899 lo repaso porque ayer no grabamos 51 00:04:44,899 --> 00:04:55,230 ¿cuál era? 52 00:04:55,550 --> 00:04:55,850 ¿dónde está? 53 00:04:55,850 --> 00:04:56,490 permanencia 54 00:04:56,490 --> 00:05:00,300 esta aquí 55 00:05:00,300 --> 00:05:03,300 donde estaba 56 00:05:03,300 --> 00:05:05,579 ¿Qué proyecto es esto? 57 00:05:06,459 --> 00:05:07,019 ¿Proc2? 58 00:05:07,779 --> 00:05:08,079 No sé 59 00:05:08,079 --> 00:05:10,220 No me acuerdo cuál es el proyecto 60 00:05:10,220 --> 00:05:22,899 ¿No se acuerda cuál es el proyecto? 61 00:05:25,410 --> 00:05:26,550 ¿Cómo mira el proyecto de aquí? 62 00:05:34,269 --> 00:05:34,889 Bueno, da igual 63 00:05:34,889 --> 00:05:36,930 Simplemente sale un 64 00:05:36,930 --> 00:05:39,750 Un fichero con varias 65 00:05:39,750 --> 00:05:41,850 Líneas, en cada línea pone 66 00:05:41,850 --> 00:05:44,009 Lo que tiene que poner 67 00:05:44,009 --> 00:05:45,910 ¿Vale? Ahora no lo encuentro 68 00:05:45,910 --> 00:05:48,449 Otras cosas 69 00:05:48,449 --> 00:05:50,069 Que hemos hecho es 70 00:05:50,069 --> 00:05:51,910 Que al iniciarse 71 00:05:51,910 --> 00:05:52,629 El 72 00:05:52,629 --> 00:05:55,750 programa, ¿vale? 73 00:05:55,769 --> 00:05:57,550 cuando se llama el init 74 00:05:57,550 --> 00:05:59,949 ¿vale? que está por aquí 75 00:05:59,949 --> 00:06:01,269 initialize, ¿vale? 76 00:06:01,730 --> 00:06:03,629 pues se llamaba este 77 00:06:03,629 --> 00:06:05,230 método de aquí, este método de aquí 78 00:06:05,230 --> 00:06:07,850 carga los datos y sostancialmente 79 00:06:07,850 --> 00:06:09,269 lo que va a ver es 80 00:06:09,269 --> 00:06:10,610 va a buscar si 81 00:06:10,610 --> 00:06:13,889 existe el fichero 82 00:06:13,889 --> 00:06:17,290 con dentro los datos 83 00:06:17,290 --> 00:06:19,209 de los alumnos 84 00:06:19,209 --> 00:06:21,850 si existe este fichero lo va cargando 85 00:06:21,850 --> 00:06:38,689 Y, sustancialmente, va reconstruyendo estos alumnos. De esta forma, cuando apago e enciendo otra vez este programa, pues me carga los alumnos que ya existían, ¿vale? Y, ¿vale? Esto funcionaba, repito, porque los alumnos eran bastante sencillos. 86 00:06:38,689 --> 00:06:50,069 Ahora, ¿qué pasa si quiero hacer las cosas un poquito mejor y si tengo estas cosas de problemas de objetos referenciados y cosas por el estilo? 87 00:06:50,670 --> 00:07:01,009 Tengo otra forma de guardar los ficheros que es utilizando, digamos, mecanismos que me proporciona la propia Java Virtual Machine 88 00:07:01,009 --> 00:07:16,110 ¿Vale? Entonces, en vez de transformar yo un objeto en una cadena de textos y guardarlo, le digo directamente a quien sea, ¿vale? Ahora lo veremos, de guardarme este objeto. Le paso un objeto y digo, guárdamelo. 89 00:07:16,110 --> 00:07:38,410 Él claramente a este punto el objeto no será un objeto inteligible por el ser humano, si yo abro ese fichero no me encontraré allí algo que puedo entender, ¿vale? Será una representación en formato de byte como le da la gana a la Java Virtual Machine del objeto que yo tengo, ¿vale? 90 00:07:38,410 --> 00:07:55,709 La ventaja que tengo con esto es que hasta un cierto nivel de complejidad sí que me mantiene las relaciones internas entre los varios objetos. Es decir, que cuando guardaré el profesor, pues el alumno con el profesor me guardará el alumno y me guardará también el profesor. 91 00:07:55,709 --> 00:08:12,769 y que si luego lo recargaré, pues los varios alumnos tendrán el mismo profesor, porque el mismo en automático como que seta un identificador, un modo de entender que este objeto no son tres copias distintas, 92 00:08:12,769 --> 00:08:19,029 si no tienen el mismo identificador, el mismo hashcode, lo que sea, 93 00:08:19,569 --> 00:08:22,029 de esta forma, cuando lo va recargando y le dice, 94 00:08:22,129 --> 00:08:24,310 oye, mira, este alumno tiene este profesor, 95 00:08:24,490 --> 00:08:27,149 y él se da cuenta que este profesor ya ha salido creado, 96 00:08:27,269 --> 00:08:31,689 ya tiene existencia en mi heap, 97 00:08:32,169 --> 00:08:34,990 pues a ese punto dice, ah, vale, entonces no lo vuelvo a crear, 98 00:08:35,169 --> 00:08:36,990 pero le asigno el mismo. 99 00:08:37,110 --> 00:08:41,009 Y haremos una prueba nosotros ahora para ver que efectivamente funciona así. 100 00:08:41,009 --> 00:08:41,750 ¿Vale? 101 00:08:42,769 --> 00:08:47,690 si el dato no es string 102 00:08:47,690 --> 00:08:49,330 habrá que convertir la string en matización 103 00:08:49,330 --> 00:08:51,529 de una matización, hemos dicho que ocurre con referencia 104 00:08:51,529 --> 00:08:53,730 a objetos, estos son los problemas si intentamos 105 00:08:53,730 --> 00:08:55,409 guardarlo como cosa, ¿vale? 106 00:08:55,929 --> 00:08:58,070 entonces, las opciones 107 00:08:58,070 --> 00:08:59,230 nosotros lo que hemos 108 00:08:59,230 --> 00:09:01,669 bueno, para obviar 109 00:09:01,669 --> 00:09:03,950 al problema que teníamos ayer 110 00:09:03,950 --> 00:09:05,409 ¿vale? existen 111 00:09:05,409 --> 00:09:07,769 varias formas, la primera forma es la que veremos 112 00:09:07,769 --> 00:09:09,350 ahora, que se llama la serialización 113 00:09:09,350 --> 00:09:11,450 ¿vale? utilizar objetos 114 00:09:11,450 --> 00:09:13,929 serializable y hacer que ellos lo guarden 115 00:09:13,929 --> 00:09:15,309 ¿Vale? Veremos ahora. 116 00:09:15,950 --> 00:09:19,669 Otras opciones son hacer una serialización textual. 117 00:09:19,830 --> 00:09:20,730 ¿Habéis visto XML? 118 00:09:22,809 --> 00:09:27,370 Habéis visto que XML es como un lenguaje de marcas, ¿vale? 119 00:09:27,470 --> 00:09:30,870 Donde yo me puedo inventar las etiquetas, ¿vale? 120 00:09:30,870 --> 00:09:36,769 Entonces, si yo lo que puedo hacer es, en vez de hacer una definición muy sencilla de este tipo, 121 00:09:38,090 --> 00:09:42,789 de una representación muy sencilla de este tipo de mi objeto, 122 00:09:42,789 --> 00:09:48,549 pues yo podría crearme, por ejemplo, un lenguaje XML que represente a mi alumno. 123 00:09:48,809 --> 00:09:52,870 Y en este lenguaje XML podría representar también al profesor. 124 00:09:53,269 --> 00:09:57,190 Y entonces el profesor dentro podría tener una referencia, un atributo, 125 00:09:57,549 --> 00:10:00,389 que sea un identificador, que sea único, 126 00:10:00,850 --> 00:10:06,129 y entonces cuando yo construyo mi XML del alumno y le asigno a un profesor, 127 00:10:06,169 --> 00:10:07,590 a este profesor le pondré un ID, 128 00:10:08,169 --> 00:10:12,029 y entonces si dos de estos elementos XML tienen el mismo ID, 129 00:10:12,029 --> 00:10:14,269 cuando lo reconstruyo tendré que 130 00:10:14,269 --> 00:10:16,129 construir el mismo objeto para los dos 131 00:10:16,129 --> 00:10:18,049 ¿vale? o sea, podría, sabéis que 132 00:10:18,049 --> 00:10:19,929 lenguaje de marcas al fin y al cabo es 133 00:10:19,929 --> 00:10:22,149 texto plano, como este 134 00:10:22,149 --> 00:10:24,210 aquí, al que se le añade 135 00:10:24,210 --> 00:10:26,070 información, meta información 136 00:10:26,070 --> 00:10:27,750 se le añade las etiquetas para 137 00:10:27,750 --> 00:10:30,309 decirle algo más, cuando era html 138 00:10:30,309 --> 00:10:32,389 todos los comandos, todas las 139 00:10:32,389 --> 00:10:34,230 etiquetas que utilizaban 140 00:10:34,230 --> 00:10:36,490 era para dar semántica 141 00:10:36,490 --> 00:10:38,529 a la web o para dar formato a la web 142 00:10:38,529 --> 00:10:40,330 cuando uso xml 143 00:10:40,330 --> 00:10:42,690 sustancialmente no estoy hablando de una página web, 144 00:10:42,789 --> 00:10:44,669 más estoy hablando de un cualquier contexto. 145 00:10:44,850 --> 00:10:49,470 Me creo un lenguaje propio mío para representar lo que yo quiera representar. 146 00:10:49,470 --> 00:10:55,750 Entonces, en este caso, sería representar mi contexto de mi aplicación 147 00:10:55,750 --> 00:10:58,250 y decirle que un alumno tiene estas características, 148 00:10:58,509 --> 00:11:01,629 luego tiene estos profesores, tiene estas asignaturas y cosas por el estilo. 149 00:11:01,970 --> 00:11:06,690 Está claro que si yo lo hago de esta forma, tengo ventajas y desventajas. 150 00:11:06,690 --> 00:11:26,809 La desventaja clara es que se vuelve complejo tanto guardar los objetos como recargarlos. Es una tarea relativamente compleja porque se requiere un algoritmo bastante complejo para que se dé cuenta de todas estas cosas de los identificadores, etc. Además de alguna forma de poder leer XML. 151 00:11:26,809 --> 00:11:33,889 Hay clases en Java que permiten leerse un XML y transformarlo en un modelo 152 00:11:33,889 --> 00:11:37,110 Para que luego yo pueda trabajar con un modelo como si fuera un objeto 153 00:11:37,110 --> 00:11:41,429 Pero tengo que saber utilizar todas estas cosas 154 00:11:41,429 --> 00:11:45,950 La ventaja que tengo con esto es que lo que se está guardando 155 00:11:45,950 --> 00:11:49,409 Es un fichero de texto inteligible por el ser humano 156 00:11:49,409 --> 00:11:52,450 Entonces yo lo estoy usando para mi aplicación 157 00:11:52,450 --> 00:12:02,429 pero nadie me prohíbe que mañana con este mismo fichero XML lo pase a otro programa, a otro lector de XML, a otra cosa 158 00:12:02,429 --> 00:12:07,049 y este pueda analizarlo y darme un esquema de lo que está escrito en ese fichero 159 00:12:07,049 --> 00:12:11,590 que yo pueda entender sin tener mi aplicación y sin encender mi aplicación. 160 00:12:12,049 --> 00:12:17,129 Así como si quiero modificarlo y quiero hacer otro programa que lo que hace es 161 00:12:17,129 --> 00:12:43,350 Pilla un fichero de texto de alumnos y de profesores y lo convierte en este XML para que luego se pueda importar dentro de mi aplicación, lo puede hacer. Si en vez lo utilizo como objetos serializados, entonces no como XML, sino como cosas que no entiendo, hacer esta operación, o sea, crear un fichero que luego sea leíble por mi aplicación va a ser más complejo. 162 00:12:43,350 --> 00:13:08,509 Sí. Y otra opción es utilizar cosas avanzadas, o sea, un object, R no me acuerdo qué es, mapping, relational mapping, no lo sé, y un sistema de base de datos, es decir, un sistema que pille los objetos, haga un mapeado de los objetos a tablas de base de datos, 163 00:13:08,509 --> 00:13:33,250 Y luego se utiliza un sistema gestor de base de datos para guardar esas tablas, guardar esta información. Sustancialmente, guardar los objetos en una base de datos. Pero claro, hay que ver cómo hacerlo eso también. Si represento una tabla que cada campo de la tabla es un atributo de mi objeto, pero esto me funciona bien solo si los atributos son todos sencillos. 164 00:13:33,250 --> 00:13:56,590 Si los atributos a su vez son objetos, pues la cosa se puede complicar. Siempre puedo hacer que sea una referencia, una clave a otra tabla donde se guardan los otros objetos. Entonces tendré la tabla alumnos y la tabla profesores y un campo de la tabla alumnos será una referencia, una clave a la tabla de profesores. Y así voy construyendo. 165 00:13:56,590 --> 00:14:09,649 Pero claro, hay que hacer un mapeado entre mi estructura a nivel de objetos y mi estructura a nivel de base de datos, ¿sí? Vamos a ver qué son los objetos serializables, ¿vale? 166 00:14:09,649 --> 00:14:21,269 en la idea pensarla así es la posibilidad de pillar un objeto y transformarlo y considerarlo 167 00:14:21,269 --> 00:14:31,009 como una secuencia de bytes vale para que esto sea posible los objetos tienen que implementar 168 00:14:31,009 --> 00:14:37,190 una clase que sea una interfaz que se llama la interfaz serializable vale y veremos que 169 00:14:37,190 --> 00:14:39,649 la interfaz serializable no tiene métodos 170 00:14:39,649 --> 00:14:40,809 ¿vale? o sea que 171 00:14:40,809 --> 00:14:43,389 directamente yo le pongo implementar serializable 172 00:14:43,389 --> 00:14:45,610 y ya lo puedo serializar 173 00:14:45,610 --> 00:14:47,289 ¿vale? la idea es que 174 00:14:47,289 --> 00:14:49,669 si un objeto no es serializable no puedo 175 00:14:49,669 --> 00:14:51,470 hacerlo pasar por un stream 176 00:14:51,470 --> 00:14:53,570 para un input stream o un output stream 177 00:14:53,570 --> 00:14:54,850 si es serializable 178 00:14:54,850 --> 00:14:57,490 la Javitor 179 00:14:57,490 --> 00:14:59,470 Machine se encargará de alguna forma 180 00:14:59,470 --> 00:15:01,230 de poderlo representar 181 00:15:01,230 --> 00:15:03,149 en un formato que se pueda 182 00:15:03,149 --> 00:15:05,429 enviar por un stream o 183 00:15:05,429 --> 00:15:06,850 leer por un stream ¿vale? 184 00:15:06,850 --> 00:15:34,870 Entonces, lo único que tenemos que hacer nosotros, sustancialmente, es serializar el objeto. Tiene que ser serializable el objeto y todos los objetos que son atributos de este objeto. Si yo tengo el objeto alumno y tengo el objeto profesor, el objeto alumno es serializable y el objeto profesor no, no puedo guardar el objeto alumno en un fichero con este método. También profesor tiene que ser serializable. 185 00:15:34,870 --> 00:15:42,350 Existe una clase, que es la clase ObjectOutputStream y la clase ObjectInputStream 186 00:15:42,350 --> 00:15:46,950 Que permiten leer o escribir un objeto directamente 187 00:15:46,950 --> 00:15:51,129 Entonces, por ejemplo, aquí tengo un ObjectOutputStream 188 00:15:51,129 --> 00:15:55,330 Que se conecta a un FileOutputStream de un fichero 189 00:15:55,330 --> 00:15:57,549 Pues esto escribirá directamente a un fichero 190 00:15:57,549 --> 00:16:03,289 Y tengo la clase WriteObject, o sea el método WriteObject de la clase ObjectOutputStream 191 00:16:03,289 --> 00:16:05,970 Que me permite pillar un objeto serializable 192 00:16:05,970 --> 00:16:08,309 y guardarlo en el fichero 193 00:16:08,309 --> 00:16:10,169 ¿vale? y después lo puedo cerrar 194 00:16:10,169 --> 00:16:10,730 si quiero 195 00:16:10,730 --> 00:16:13,929 para leerlo, está el object 196 00:16:13,929 --> 00:16:16,190 input stream, que se conecta 197 00:16:16,190 --> 00:16:18,669 igualmente con un file input stream 198 00:16:18,669 --> 00:16:19,490 a un fichero 199 00:16:19,490 --> 00:16:21,629 y tengo la 200 00:16:21,629 --> 00:16:23,649 función read object 201 00:16:23,649 --> 00:16:26,110 la función read object leerá un objeto 202 00:16:26,110 --> 00:16:27,690 ¿vale? entonces cuidado 203 00:16:27,690 --> 00:16:29,570 porque si he guardado un alumno 204 00:16:29,570 --> 00:16:32,009 cuando lo voy a leer, lo leeré como objeto 205 00:16:32,009 --> 00:16:34,049 y tendré que hacer algún tipo 206 00:16:34,049 --> 00:16:34,690 de casting 207 00:16:34,690 --> 00:16:59,700 O mirar con InstanceOff si es una clase de alumno y luego hacerla, o intentar hacerla con un try-catch en el caso en que no sea de la clase que yo estaba intentando castear, lo que pasará es que saltará una PlasticShip. 208 00:16:59,700 --> 00:17:07,160 Muy bien, entonces también se utiliza la serialización para transmitir objetos por una red 209 00:17:07,160 --> 00:17:13,660 Lo mismo desde aquí se hace cuando en vez de escribir en ficheros se utilizan sockets 210 00:17:13,660 --> 00:17:21,019 Que sustancialmente crean un punto de acceso entre varias aplicaciones que están en un ordenador distinto 211 00:17:21,019 --> 00:17:26,740 Se comunican por red, más de esto en segundos de DAM en procesos y servicios 212 00:17:26,740 --> 00:17:29,740 pues la cosa es la misma 213 00:17:29,740 --> 00:17:31,740 en vez de escribir, siempre se usará 214 00:17:31,740 --> 00:17:33,880 input stream y output stream 215 00:17:33,880 --> 00:17:35,359 en vez de file output stream 216 00:17:35,359 --> 00:17:37,019 se usará el output stream directamente 217 00:17:37,019 --> 00:17:39,700 pero la idea es que yo tendré un objeto 218 00:17:39,700 --> 00:17:41,599 lo transformaré en una secuencia 219 00:17:41,599 --> 00:17:43,539 de bytes sustancialmente y lo paso 220 00:17:43,539 --> 00:17:45,380 por un canal de comunicación, este canal 221 00:17:45,380 --> 00:17:47,579 en vez de llegar al disco duro y escribirse 222 00:17:47,579 --> 00:17:49,839 en el disco duro, llegará a otra aplicación 223 00:17:49,839 --> 00:17:51,339 que estará allí con un input stream 224 00:17:51,339 --> 00:17:53,700 y leerá la información 225 00:17:53,700 --> 00:17:54,740 que se le envía 226 00:17:54,740 --> 00:17:59,039 en ambos casos la Java Virtual Machine gestiona el formato de los datos de los objetos 227 00:17:59,039 --> 00:18:01,059 y los objetos serializados 228 00:18:01,059 --> 00:18:04,440 entonces es la Java Virtual Machine que me dice cómo se guardan 229 00:18:04,440 --> 00:18:06,480 y cómo tengo que hacerlo 230 00:18:06,480 --> 00:18:08,980 no tengo que hacerlo yo, como siempre 231 00:18:08,980 --> 00:18:13,099 ventaja, es más sencillo porque me olvido de cómo se hace 232 00:18:13,099 --> 00:18:14,359 le digo simplemente hazlo 233 00:18:14,359 --> 00:18:17,799 desventaja, no tengo control directo sobre estas cosas 234 00:18:17,799 --> 00:18:20,720 estoy cediendo el control a la Java Virtual Machine 235 00:18:20,720 --> 00:18:23,059 entonces si luego hace algo que no me gusta 236 00:18:23,059 --> 00:18:29,119 pues es un problema mío 237 00:18:29,119 --> 00:18:32,440 hay inconvenientes de la serialización 238 00:18:32,440 --> 00:18:34,559 la clase Object AutoStream 239 00:18:34,559 --> 00:18:37,720 tiene algunos problemillas 240 00:18:37,720 --> 00:18:39,460 se lía a veces 241 00:18:39,460 --> 00:18:42,240 en particular en dos casos 242 00:18:42,240 --> 00:18:45,799 el primer caso es cuando intentamos reutilizar 243 00:18:45,799 --> 00:18:48,539 una misma referencia para serializar 244 00:18:48,539 --> 00:18:49,859 objetos diferentes 245 00:18:49,859 --> 00:18:52,559 tengo una referencia a un objeto 246 00:18:52,559 --> 00:18:55,019 lo mando, lo serializo, lo escribo en fichero 247 00:18:55,019 --> 00:18:58,680 ahora en esta referencia cambio el objeto y lo vuelvo a escribir 248 00:18:58,680 --> 00:19:02,680 a veces puede dar problemas, o si tengo un objeto 249 00:19:02,680 --> 00:19:06,259 lo escribo, ahora lo modifico usando setter y getter 250 00:19:06,259 --> 00:19:11,019 y luego lo intento escribir otra vez, puede que funcione mal 251 00:19:11,019 --> 00:19:14,660 esto deriva también de algunos problemas 252 00:19:14,660 --> 00:19:18,740 de optimización que tiene, en el que por ejemplo 253 00:19:18,740 --> 00:19:21,980 esto se ve mucho cuando se usan sockets 254 00:19:21,980 --> 00:19:46,299 ¿Vale? Como yo tengo que enviar objetos, cuando yo te envío un objeto, ¿vale? Tú lo guardas y le das un identificador tuyo de esta transferencia. Si te vuelven a mandar el mismo objeto y te lo han mandado antes, en vez de gastar recursos de red y volver a mandarlo, tú asumes que ya me lo has mandado este objeto, pues ya lo tengo, no lo vuelvo a recibir otra vez. 255 00:19:46,299 --> 00:20:04,000 Lo pillo de una caché interna que tengo yo y te digo, mira, aquí lo tienes. El problema es que si yo he pillado el objeto, te lo he mandado, ahora lo modifico y te lo mando otra vez, como es la misma referencia, el mismo objeto, él cree que no ha cambiado, cree que ya lo tiene y va a pillar el objeto que tenía antes, sin la modificación que se ha hecho. 256 00:20:04,000 --> 00:20:17,480 Entonces hay que saberlo para que en situación como esta, cuando guardo ficheros, a veces me está guardando ficheros sin las modificaciones y tendré que hacer algo para que se dé cuenta de eso y que me lo vuelva a guardar desde cero. 257 00:20:18,359 --> 00:20:22,099 El segundo problema es la cabecera del fichero serializado. 258 00:20:22,099 --> 00:20:44,039 Cuando yo guardo un fichero serializado, al principio no se guardan directamente los objetos como hemos hecho ayer, que simplemente se guardaban las filas, entonces ya la primera fila era un objeto, sino que este fichero tiene al principio una cabecera, tiene una serie de datos iniciales que sirven a Java Virtual Machine para decir, 259 00:20:44,039 --> 00:20:50,099 oye, mira, soy un fichero de objetos, pues a partir de aquí empiezan los objetos de beta. 260 00:20:50,660 --> 00:20:53,980 Ningún problema. Tú lo usas, escribes los ficheros, ningún problema. 261 00:20:54,200 --> 00:20:58,900 El problema surge en el que si tú tienes un fichero, guardas algunos objetos, 262 00:20:59,579 --> 00:21:05,960 luego apagas la aplicación, mañana enciendes la aplicación, creas objetos nuevos 263 00:21:05,960 --> 00:21:12,619 y los quieres guardar en el mismo fichero de ayer, añadiendoselo a continuación, 264 00:21:12,619 --> 00:21:29,119 Como él, hasta si le pones la append, pues va a escribir después, pues como piensa que sea una nueva escritura, vuelve a añadir la cabecera. Entonces tengo un fichero que tiene una cabecera, una serie de objetos, otra vez la cabecera y otra vez los objetos. 265 00:21:29,119 --> 00:21:43,740 Y esto, cuando luego lo irá a leer, pues le causará un problema, porque él después de la cabecera se espera todos los objetos, de repente se encuentra otra vez la cabecera, lo intenta interpretar como objeto, no lo consigue, entonces me lanza un exceso, ¿vale? 266 00:21:43,740 --> 00:21:56,319 Y este problema aquí sí que lo vamos a simular ahora, vamos a hacer algo que funcione todo bien, y luego después vamos a forzar que haya varios errores para ver cómo podemos un poquito gestionarlos, ¿vale? 267 00:21:57,079 --> 00:22:04,380 Por esta razón, esto de la serialización directa pura, pues no se suele utilizar, ¿vale? 268 00:22:04,440 --> 00:22:10,680 Es decir, en proyectitos básicos, en cosas sencillas, en cosas por estilo, sí se puede utilizar, es bastante fácil. 269 00:22:11,240 --> 00:22:19,339 Si yo tengo un sistema de gestión de varios objetos mucho más complejos, con muchos objetos y gestionar muchas cosas, 270 00:22:19,339 --> 00:22:47,819 pues lo más probable es que llegue un momento en que trabajar con este tipo de comunicación llega a demasiada complejidad, entonces me da demasiados errores, pues entonces compensa crearse un sistema de persistencia mejor basado sobre un ORM y un SGBD, o sea, un sistema gestor de datos, como por ejemplo Hibernate y cosas por el estilo. 271 00:22:47,819 --> 00:23:02,180 Pero no es una cosa sencilla que hago, oye, mira, doy clic aquí y aquí y me funciona. Tengo que entender qué es Hibernate, tengo que entender qué son estas cosas y practicarlo. El próximo curso creo que lo veréis. 272 00:23:02,180 --> 00:23:05,220 en DAM, aquí yo doy DAM 273 00:23:05,220 --> 00:23:07,000 entonces me lo sé mejor las asignaturas 274 00:23:07,000 --> 00:23:09,160 en DAM seguramente hay una asignatura 275 00:23:09,160 --> 00:23:10,559 dedicada a eso que se llama 276 00:23:10,559 --> 00:23:12,180 accesos a datos 277 00:23:12,180 --> 00:23:14,579 eso va todo de 278 00:23:14,579 --> 00:23:16,720 bases de datos y conexiones 279 00:23:16,720 --> 00:23:18,880 de datos normales, no relacionales, etc 280 00:23:18,880 --> 00:23:21,319 y como desde una aplicación 281 00:23:21,319 --> 00:23:22,579 puedo conectarme a eso 282 00:23:22,579 --> 00:23:25,519 pero estoy convencido a un 95% 283 00:23:25,519 --> 00:23:26,700 que también en DAO 284 00:23:26,700 --> 00:23:29,740 en la parte sobre todo de programación 285 00:23:29,740 --> 00:23:30,700 lado servidor 286 00:23:30,700 --> 00:23:32,559 si que hay una parte 287 00:23:32,559 --> 00:23:34,880 de acceso a datos 288 00:23:34,880 --> 00:23:36,980 y entonces 289 00:23:36,980 --> 00:23:38,619 allí es cuando veréis estas cosas 290 00:23:38,619 --> 00:23:39,880 más en profundidad 291 00:23:39,880 --> 00:23:43,019 a partir de aquí, estos son ejemplos 292 00:23:43,019 --> 00:23:44,640 de escritura y lectura 293 00:23:44,640 --> 00:23:46,319 en ficheros y cosas por el estilo 294 00:23:46,319 --> 00:23:49,019 lo tenéis como código para echarle un vistazo 295 00:23:49,019 --> 00:23:49,380 ¿vale? 296 00:23:49,980 --> 00:23:51,680 algunos de estos ya los hemos hecho 297 00:23:51,680 --> 00:23:54,160 por ahora no hemos trabajado mucho con binarios 298 00:23:54,160 --> 00:23:56,900 pero ayer si que lo vimos un poquito en clase 299 00:23:56,900 --> 00:23:58,279 cosas por el estilo, como se lee 300 00:23:58,279 --> 00:23:59,839 se escribe un ejemplo ¿vale? 301 00:23:59,839 --> 00:24:03,619 Podéis buscar también otras formas de hacer estas cosas. 302 00:24:04,519 --> 00:24:13,559 Este es el ejemplo que nos interesa particularmente ahora, que es de escribir utilizando Object Output Stream, ¿vale? 303 00:24:13,660 --> 00:24:22,160 Entonces, si os fijáis aquí, creo un Object Output Stream y luego escribo varios objetos, ¿vale? 304 00:24:22,299 --> 00:24:28,779 En particular, está un objeto, está un método que es WriteObject, que me permite escribir cualquier tipo de objeto, 305 00:24:28,779 --> 00:24:45,480 Pero luego, si yo quiero, en vez de escribir un objeto, escribir un entero, un booleano, un char, en general un tipo primitivo, tengo métodos que sostancialmente me converten el tipo primitivo en un objeto. 306 00:24:45,480 --> 00:24:58,319 Sabéis que cada tipo primitivo tiene una clase wrapper que sostancialmente transforma en un objeto equivalente el tipo primitivo, pues lo que hace es que luego lo escribe. 307 00:24:58,779 --> 00:25:04,119 también tenemos write to tf que es para poder escribir strings vale utilizando 308 00:25:04,119 --> 00:25:10,960 esto para leerlo lo mismo tengo read boolean, read double, read char, read int y en 309 00:25:10,960 --> 00:25:15,400 particular lo que nos interesa más a nosotros es para poder leer un objeto 310 00:25:15,400 --> 00:25:20,400 que es el read object vale y esto te lee un objeto directamente este es un 311 00:25:20,400 --> 00:25:25,299 ejemplo de cómo se realiza una clase aquí tenemos la clase persona que 312 00:25:25,299 --> 00:25:30,160 normal y corriente una persona toda la vida vale lo que tenemos que hacer para 313 00:25:30,160 --> 00:25:36,359 que pueda ser escrita en un fichero es implementar serializable ahora este 314 00:25:36,359 --> 00:25:42,160 serializable no añade ningún método directamente es simplemente digamos como 315 00:25:42,160 --> 00:25:49,339 un flag para decir a la java virtual machine que esta persona este 316 00:25:49,339 --> 00:25:57,019 objeto si se puede guardar en un en un fichero o de toda forma utilizar con un 317 00:25:57,019 --> 00:26:02,019 input stream y un output stream es serializable es transformable en un 318 00:26:02,019 --> 00:26:07,759 stream vale entonces un objeto serializable como se escribe vale aquí 319 00:26:07,759 --> 00:26:11,539 tengo las personas y veis que aquí lo que estoy haciendo es un bright object 320 00:26:11,539 --> 00:26:15,200 de la persona bright object de la persona pues éstos me lo 321 00:26:15,200 --> 00:26:20,960 escribirá en este fichero de aquí vale aquí se está utilizando una 322 00:26:20,960 --> 00:26:27,460 una ruta absoluta pero mejor utilizar rutas 323 00:26:27,460 --> 00:26:33,859 relativas y para leerlo lo mismo tened en cuenta que pero cuando lo leo vale 324 00:26:33,859 --> 00:26:42,039 esto será un objeto entonces tendré que hacer un cast al tipo de objeto 325 00:26:42,039 --> 00:27:04,819 Entonces aquí, por ejemplo, está utilizando para poder utilizarlo un available. Está diciendo que mientras que haya bytes disponibles para leer, pues leeme otra persona. Cuando este de aquí, el available, me dirá que no hay nada, entonces me dará cero, pues habré llegado al final de la lectura de los objetos. 326 00:27:04,819 --> 00:27:15,039 Y ya está. Es un método de hacerlo. Hay otros. La última cosa que nos puede interesar un mínimo es la jerarquía de clases que hemos visto hasta ahora. 327 00:27:16,160 --> 00:27:28,700 Entonces, nosotros sabemos que hay input stream y output stream. A partir de aquí hay clases que pillan este input stream, que es una secuencia de datos en entrada, 328 00:27:28,700 --> 00:27:45,920 Y me añaden algunas funcionalidades más para que sea más fácil para mí utilizarla. Nosotros hemos utilizado, por ejemplo, el File Input Stream, que lo que hace es añadir el concepto de que no estoy leyendo desde cualquier sitio, sino desde un fichero. 329 00:27:45,920 --> 00:28:09,059 Entonces me añadirá algunas ventajas, alguna posibilidad más para poder trabajar con ficheros. Hay más, ¿vale? Hay otras cosas que están por allí y también existen, por ejemplo, Buffered Input Stream y cosas por el estilo que mejoran todavía la posibilidad de leer de ficheros, etc. 330 00:28:09,059 --> 00:28:23,279 Lo mismo para OutputStream, luego están los Reader y los Writer. Hemos dicho que estos trabajan con bytes, mientras que estos de aquí trabajan con caracteres. 331 00:28:23,279 --> 00:28:26,539 fijaos que InputStream, ObjectInputStream 332 00:28:26,539 --> 00:28:29,640 está en el lado de estoy trabajando como bytes 333 00:28:29,640 --> 00:28:32,279 porque al fin y al cabo lo que se está guardando 334 00:28:32,279 --> 00:28:35,119 y lo veremos ahora abriendo un fichero guardado 335 00:28:35,119 --> 00:28:37,500 que sustancialmente no es 336 00:28:37,500 --> 00:28:43,319 no se entiende 337 00:28:43,319 --> 00:28:45,180 algunos trozos a lo mejor sí 338 00:28:45,180 --> 00:28:47,160 pero algunos otros no 339 00:28:47,160 --> 00:28:48,240 dudas