840 likes | 988 Views
Capítulo VI - Strings, I/O,Formatting,and Parsing. Usar String, StringBuffer y StringBuilder Archivos I/O usando el paquete java.io Serializacion usando el paquete java.io Trabajando con Dates, Number y Currencies Uso de expresiones regulares. String, StringBuffer y StringBuilder.
E N D
Capítulo VI - Strings, I/O,Formatting,and Parsing • Usar String, StringBuffer y StringBuilder • Archivos I/O usando el paquete java.io • Serializacion usando el paquete java.io • Trabajando con Dates, Number y Currencies • Uso de expresiones regulares
String, StringBuffer y StringBuilder • En Java 5 se aumento la clase StringBuilder, que tiene la misma funcionalidada que StringBuffer, la diferencia es que StringBuilder no es sincronizada, mientras que StringBuffer si lo es. • Por lo tanto StringBuilder es mucho mas rapido.
Clase String • Strings con objetos inmutables • En java cada carácter es un String • Son caracteres Unicode de 16 bits. • Eje: • String s = new String(); • s = “abc”; • S = new String(“abc”); • Inmutabilidad: Una ves que fue asignado un valor, este no puede cambiar. • Los String son imnutables, pero sus referencias no.
Procesos.. • String s = “abcdef”; • s.concat(“ ghij”); • Como resultado tenemos s = “abcdef ghij”, que es lo que paso aquí???? • Se crearon 3 objetos String, el primero “abcdef”, el segundo, “ ghij” y el tercero, “abcdef ghjij“. • En donde solo “abcdef ghjij” esta referenciada, y vamos a decir que esta “perdida”, puesto que no se las puede acceder desde nuestro contexto.
Otro ejemplo • String x = "Java"; • x.concat(" Rules!"); • System.out.println("x = " + x);
Y asi pasará si aplicamos los distintos metodos de la clase String • x.toUpperCase(); • x.replace('a', 'X'); • Pero si se hace • x = x.concat(“ Rules!”);
Factores importantes sobre String y Memoria • Para un buen manejo de la maquina virtual, se creo la “String constant pool” en java, que es donde son puestos los objetos String. • Cuando el compilador ver un String, verifica en el pool y si existe referencia la variable a ese String ya existente. • Es asi que varias variables de referencia pueden estar apuntando al mismo String. • Es por esto tambien que la clase String está marcada como final, para que no se pueda cambiar el comportamiento de la clase.
Creando un nuevo String • En s = “abc”; • En este caso abc va al pool de String, referiado por s. • En s = new String(“abc”); • En este caso el objeto se crea en memoria normal como otro objeto mas y en el pool de String.
Métodos Importante de la clase String • Metodos usados comunmente y que se veran en el examen. • charAt(): Retorna el caracter localizado en el indice dado. • concat(): Agrega un String al final de otro. • equalsIgnoreCase(): Determina si dos String son iguales, ignorando case • length(): Devuelve el numero de caracteres. • replace(): Reemplaza las ocurrencias con un caracter dado. • substring(): Retorna una parte del String. • toLowerCase(): Convierte a minuscula. • toString(): Retorna el valor String. • toUpperCase(): Convierte a mayuscula. • trim(): Remueve los espacios en blanco al final del String.
public char charAt(int index) • El indice empieza en cero. • String x = "airplane"; • System.out.println( x.charAt(2) ); • public String concat(String s) • String x = "taxi"; • System.out.println( x.concat(" cab") ); • Los operadores + y += tienen la misma funcionalidad que concat. • String x = "library"; • System.out.println( x + " card"); • String x = "Atlantic"; • x += " ocean" • System.out.println( x ); Salida: r Salida: taxicab Salida: library card Salida: Atlantic ocean
public boolean equalsIgnoreCase(String s) • Retorna verdad si es que los String son iguales, sin importar el case. • String x = "Exit"; • System.out.println( x.equalsIgnoreCase("EXIT")); // "true" • System.out.println( x.equalsIgnoreCase("tixe")); // "false“ • public int length() • Retorna la longitud del String • String x = "01234567"; • System.out.println( x.length() ); • public String replace(char old, char new) • El nuevo aracter es reemplazado por el nuevo • String x = "oxoxoxox"; • System.out.println( x.replace('x', 'X') ); Retorna: "8" Salida: oXoXoXoX
public String substring(int begin) • El indice empieza desde cero, y devuelve desde el indice indicado hasta el final del string. • public String substring(int begin, int end) • El indice begin tambien empieza en cero, pero el segundo argumento, empieza en 1 e indica hasta donde tomar el String, los dos desde el primer caracter del string. • Eje: • String x = "0123456789"; • System.out.println( x.substring(5) ); Salida: 56789 • System.out.println( x.substring(5, 8)); Salida: 567
public String toLowerCase() • Convierte a minuscula • String x = "A New Moon"; • System.out.println( x.toLowerCase() ); • public String toString() • Retorna el String del string, por que esta??, porque todos objetos tienen este metodo. • String x = "big surprise"; • System.out.println( x.toString() ); • public String toUpperCase() • Retorna el string en mayusculas • String x = "A New Moon"; • System.out.println( x.toUpperCase() ); Salida: a new moon Salida: A NEW MOON
public String trim() • Retorna el string sin los espacios de adelante y ni los de atrás. • String x = " hi "; • System.out.println( x + "x" ); Salida: " hi x " • System.out.println( x.trim() + "x"); Salida: " hix "
Clases StringBuffer y StringBuilder • Estas clases se hacen importante cuando se quiere hacer manejo de grandes cantidades de strings. • Dado que sabemos que los String son inmutables, si es que manejamos grandes cantidades de strings asi no mas, acaberemos por llenar el pool de strings. • Se recomienda el uso de estos objetos cuando se va a trabajar con archivos I/O, asi no se usa el pool y se trabaja con estos string en mismo segmento de memoria.
StringBuffer vs. StringBuilder • StringBuilder salio en Java 5, y tiene exactamente el mismo API que StringBuffer, la diferencia radica en que StringBuilder no es thread safe, o sea que sus metodos no tienen synchronize. • Sun recomienda usar cuando sea posible StringBuilder porque es mucho mas rapido. • En el examen puede que se ecuentre preguntas con entre estos dos objetos, pero sera cuando se trate sobre theads safe.
Usando StringBuilder y StringBuffer • Ya se habia discutido sobre los metodos de String, sobre la existencia del pool y los string dejados ahí. • Ahora los string son tratados como objetos, y como tal, los cambio hechos a su contenido, es aplicado sin necesidad de estar haciendo asignaciones extras. • Eje: • StringBuffer sb = new StringBuffer("abc"); • sb.append("def"); • System.out.println("sb = " + sb); • Y asi todos los metodos en si, puedes ser aplicados en cadena. • Eje: • StringBuilder sb = new StringBuilder("abc"); • sb.append("def").reverse().insert(3, "---"); • System.out.println( sb ); Salida: abcdef Salida: fed---cba
public synchronized StringBuffer append(String s) • Agrega el parametro que se pasa al final del String. Acepta boolean, char, double, float, int, long y otros. • Eje: • StringBuffer sb2 = new StringBuffer("pi = "); • sb2.append(3.14159f); • public StringBuilder delete(int start, int end) • Elimina el texto desde el indice start(desde cero), hasta el indice end (desde uno). • Eje: • StringBuilder sb = new StringBuilder("0123456789"); • System.out.println(sb.delete(4,6)); Metodos importantes Salida: pi = 3.14159 Salida: 01236789
public StringBuilder insert(int offset, String s) • Inserta en el objeto el String s en la posicion offset pasada, la cual empieza en cero. • Eje: • StringBuilder sb = new StringBuilder("01234567"); • sb.insert(4, "---"); • System.out.println( sb ); • public synchronized StringBuffer reverse() • Reversa el orden de los caracteres, poniendo el primero al ultimo y el ultimo en el primero. • Eje: • StringBuffer s = new StringBuffer("A man a plan a canal Panama"); • sb.reverse(); • System.out.println(sb); Salida: 0123---4567 Salida: amanaP lanac a nalp a nam A
public String toString() • Retorna el valor del objeto como String • StringBuffer sb = new StringBuffer("test string"); • System.out.println( sb.toString() ); Salida: test string
Ojo para el Examen • En el examen se verán mas ejemplos de uso de “metodos encadenados”. Pero no se verán mas de 3. • Resultado = metodo1().metodo2(). metodo3(); • Tips para saber llevar estos casos. • Determinar el método de mas a la izquierda. • SI hay un segundo método, el resultado del primero, invoca al segundo y este será el resultado. • Si existe un tercero, el resultado del segundo llama al tercero, y el resultado de este será el resultado final. • Eje: • String x = "abc"; • String y = x.concat("def").toUpperCase().replace('C','x'); • System.out.println("y = " + y); Salida: y = ABxDEF
Navegacion Archivos y I/O • El examen esta limitado a I/O de archivos para caracteres y serializacion. • Cosas que se necesitan saber. • File: El API dice que es una clase abstracta para la representación de archivos, con la cual se trabaja a un nivel alto, haciendo nuevos archivos, buscando y borrandolos, creando directorios, y trabajando con rutas. • FileReader: Clase usada para lectura de caracteres en archivos. El método read(), permite leer carácter por carácter, o un numero de caracteres. Generalmente esta wrapped, en clases como BufferedReader, que tienen métodos mejorados y mejoran el tratos de datos.
BufferedReader: Hace mas eficiente el FileReader, lee grandes pedazos de datos como archivos y los mantiene en un buffer, lo que reduce el numero de veces de acceso al archivo en bajo nivel. Tiene el método readLine(), que lee toda una línea de un archivo. • FileWriter: Clase para escribir caracteres a un archivo. Su método write() escribe caracteres o String en el archivo, es de bajo nivel. Wrapped en clases de alto nivel como BufferedWriter, PrintWritter que dan un mejor rendimiento y métodos mas flexibles para el manejo de datos. • BufferedWriter: Hace mas eficiente al FileWriter, escribe grandes pedazos de datos minimizando el numero de acceso al archivo en nivel bajo. Tiene el método newLine(), crea un separador de línea para la plataforma usada.
PrintWriter: Ha sido mejorada en Java 5, permite manejar de manera mas flexible los datos, con metodos como format(), printf() y append().
Ojo En el examen • Las clases Stream son usadas para escribir bytes, y los Readers y Writers son usados para escribir caracteres, Si se ve una clase del API que contiene la palabra Stream como DataOutputStream, entonces la pregunta debe de tratarse sobre serializacion o algo no relacionado al objetivo actual.
Creando Archivos usando la clase File • Es indispensable saber que cuando se habla de la clase File se esta hablando de la representación de archivos o directorios que existen en el disco. • class Writer1 { • public static void main(String [] args) { • File file = new File("fileWrite1.txt"); • } • } Aquí todavía no hay archivo • Si se hace lo anterior NO se crea el archivo. Solo se está creando un nombre de archivo.
Que se puede hacer con la clase File class Archivos2 { public static void main(String [] args) { try { // warning: exceptions possible boolean newFile = false; File file = new File // it's only an object ("fileWrite1.txt"); System.out.println(file.exists()); newFile = file.createNewFile(); System.out.println(newFile); System.out.println(file.exists()); } catch(IOException e) { } } } // Existe archivo?? // Talvez lo crea // Verificar si lo creo // Existe archivo?? Primera Salida: false true true Segunda Salida: true false true
Usando FileWriter y FileReader • Estas clases probablemente no se los vaya usar, porque generalmente se usa un wrapper. • Ver ejemplo Writer2.java • FileWriter fw = new FileWriter(file) hace 3 cosas: • Crea referencia fw • Crea nuevo objeto FileWriter • Crea un archivo vacio. • El metodo read del objeto FileReader pone en el arreglo de int los caracteres en el archivo.
flush y close, cuando se trabaja con stream, ocurrirá algo de buffering, y no se sabe cuando exactamente se será enviado, asi que se puede usar flush para enviar los datos en ese momento. • Y el close, se lo debe usar ya que cuando se hace lectura o escritura, se usan recursos del sistema que son caro y limitados , y este método los libera.
Consejo para el uso de clases de manejo de archivos: • 1. Ver una clase que maneje File en su constructor. • 2. Encontrar un método que se apegue mas a lo que buscamos. • 3. Ver que pide el constructor y pasarle en objeto, en base a lo que pide, como por ejemple el PrintWriter tiene algunos constructores, usar el mas fácil. • OJO: En el examen se verifica el conocimiento de las clases encadenandolas, asi que se recomienda estudiar el pequeño API para saber que es legal.
Trabajando con archivos y directorios • Para empezar, la clase File puede servir para borrar, renombrar, determinar si existe un archivo o directorio, diferencia entre ambos, etc. • Creacion de un archivo, dos maneras: • 1. Metodo createNewFile() • File file = new File("foo"); //archivo no creado • file.createNewFile(); • 2. Crear un Reader, Writer o Stream. Específicamente un FileReader, FileWriter, a PrintWriter, a FileInputStream, o FileOutputStream.
Creacion de un directorio. Se puede hacer uso del metodo mkDir() • File myDir = new File("mydir"); // crea el objeto • myDir.mkdir(); //crea el directorio • Una vez creado el diretorio, se puede trabajar con este • File myFile = new File(myDir, "myFile.txt"); • myFile.createNewFile(); • CUIDADO: Hemos visto la creacion de directorios y archivos, pero cuidado.
Si tenemos: • File myDir = new File("mydir"); • // myDir.mkdir(); // No se crea el directorio • File myFile = new File( • myDir, "myFile.txt"); • myFile.createNewFile(); • Tendremos un problema, puesto que aquí no crea el directorio, arrojara un excepcion: • java.io.IOException: No such file or directory • Ver Ejemplo Archivo3.java
Eliminación de archivos y directorios • Ver ejemplo Archivos4.java • Consideraciones: • Borrar: No se puede borrar un directorio si no esta vacio. • Renombrar: Se le tiene que pasar al objeto File existente un nombre valido. • Renombrar: Si se puede renombrar a un directorio aun si no esta vacio.
Búsqueda: • Ver ejemplo Archivo5.java • El argumento que se pasa es el nombre del archivo, y devuelve una lista del contenido del directorio.
Serialización • La idea principal de la serialización en los archivos, con objetos, es poder grabar los objetos, con los estados de sus atributos. • Y una vez guardados, poder recuperarlos tal como se lo guardo, todo esto sin tener que hacer nada mas que utilizar los métodos que ya tienen las clases.
Trabajando con ObjectOutputStream y ObjectInputStream • Dos métodos básicos, uno para serializar y escribir al archivo y otro para leer y deserializar. • ObjectOutputStream.writeObject() //Serializar y escribir • ObjectInputStream.readObject() //leer y deserializar • Estas clases son wrapper (de alto nivel), y que talvez se tenga que usar una de bajo nivel como FileOutputStream y FileInputStream. • Ver ejemplo SerializeCat.java
Objetos Graphs • En resumen el “Object Graphs” es el conjunto de atributos que tiene un objeto. Y la clase ObjectOutputStream se encarga de serializar todos los atributos aunque sean otros objetos. • Algo importante es que todos los objetos que se vayan a pasar, tiene que se ser serializables. • Ver ejemplo SerializeDog.java
Consideraciones • Que pasa si es que un objeto que es usado como atributo, no se puede ser serializado, ya se porque: • Es una clase final y no se la puede modificar • Si no es final, y tiene atributos que no pueden ser serializados. • O porque simplemente no se puede usar una subclase en el modelo. • Pero aun se quiere serializar… Entonces, la solución que se propone es marcar al atributo como transient, lo que pasará será que no se pone ala tributo dentro de la serialización. • Ver ejemplo SerializeDog2.java • Pero que pasa con el atributo ????
Usando writeObject() y readObject() • La alternativa que se da en implementar los métodos writeObject para OutputStream y readObject para InputStream. • Dentro de estos metodos se pone el codigo con el cual se pueden guardar atributos extras a los atributos de la clase principal, pero que son los valores que corresponden a los objetos que no pudieron ser serializados. • Al momento de serializar o deserializar el objetos, estos métodos son invocados. • Ver ejemplo SerializeDog3.java
Analisis… • Los métodos sobrescritos pueden lanzar excepciones, pero se recomienda manejarlos • EL método defaultWriteObject() y defaultReadObject() que se invoca al principio, indica a la JVM que se haga la serializacion normal y luego se haga algo extra. • Se pueden escribir cosas extras, antes o después del método default, pero al momento de leerlo, se lo tiene que hacer en el mismo orden. • EL método defaultReadObject() maneja la deserialización si no se implementa el método readObject(). • Finalmente se leyó el atributo extra guardado, justo después del defaultReadObject(), para seguir el orden de guardado.
Como la herencia afecta la serialización • Cuando se hace una deserializacion, la clase que se recupera, no pasa por el constructor. • Los atributos declarados como transient, se inicializan con su valor por defecto, dentro del contexto de inicialización de variable de una clase. • Que pasa si es que la superclase no es serializable, la subclase lo será?? • Punto importante: Los atributos heredados de las clases que no son serializables, al deserializar se iniciaran con los valores que se les da en el constructor o valores por default, no con el valor que fueron guardados. • OJO: para el examen se querrá saber que variables y cuales no se restauraran con los valores que fueron guardados.
Ver ejemplo SuperNotSerial.java y analizar • Por ultimo: Cuando se serializa una Collection o un arreglo, todos los elementos tienen que ser serializables. Uno solo que no lo sea, y fallará toda la serializacion.
Serializacion no es para Staticsz • Las variables estaticas NUNCA son guardadas, ya que lo que se guarda es el estado, y estas no pertenecen a la instancia de la clase.
NOTAS: • DataInputStream y DataOutputStream no serán evaluadas. • Cuando se vaya deserializar, la clase serializada y deserilizada tienen que estar en la misma versión. Si son diferentes versiones, puede haber problemas.
Dates, Numbers, y Currency • Clases relacionadas con fechas que se necesitan saber: • java.util.Date: Casi todos los metodos estan deprecated, se puede usar de puente entre Calendar y DateFormat. Representa una fecha mutable. • java.util.Calendar: Cantidad de metodos para convertir y manipular fecha y horas. • java.text.DateFormat: Da estilo a formato de la fecha, y tambien usa locale para uso internacional. • java.text.NumberFormat: Usado para formatear numeros. • java.util.Locale: Trabaja en conjunto con las dos anteriores y permite dar un formato mas rapido de acuerdo a donde se encuentren.
Clase Date • Representa la fecha y la hora. • Internamente esta representado por un long primitivo que tiene los milisegundos desde el 1 de Enero de 1970 hasta la fecha que se quiere tener. • Ejemplo: • import java.util.*; • class TestDates { • public static void main(String[] args) { • Date d1 = new Date(1000000000000L); // a trillion! • System.out.println("1st date " + d1.toString()); • } • }
Clase Date (cont…) • La mayoria de los metodos has sido deprecated, pero todavia es aceptable usar getTime() y setTime(). • Aunque es trabajoso usar milisegundos. • Ejemplo: Se agrega una hora al anterior • class TestDates2 { • public static void main(String[] args) { • Date d1 = new Date(1000000000000L); // a trillion! • System.out.println("1st date " + d1.toString()); • d1.setTime(d1.getTime() + 3600000); // 3600000 millis / hour • System.out.println("new time " + d1.toString()); • } • }