PRINCIPIOS DE MANEJO DE FICHEROS O ARCHIVOS

Aunque el manejo de archivos tiene características especiales, Java ofrece las siguientes posibilidades:

Existen las clases FileInputStream y FileOutputStream (extendiendo InputStream y OutputStream) que permiten leer y escribir bytes en archivos. Para archivos de texto son preferibles
FileReader (desciende de Reader) y FileWriter (desciende de Writer), que realizan las mismas funciones. Se puede construir un objeto de cualquiera de estas cuatro clases a partir de un String que contenga el nombre o la dirección en disco del archivo o con un objeto de la clase File que representa dicho archivo. Por ejemplo el código:

FileReader fr1 = new FileReader(“archivo.txt”);

Es equivalente a:

File f = new File(“archivo.txt”);
FileReader fr2 = new FileReader(f);

Si no encuentran el archivo indicado, los constructores de FileReader y FileInputStream pueden lanzar la excepción java.io.FileNotFoundException.
Los constructores de FileWriter y FileOutputStream pueden lanzar java.io.IOException. Si no encuentran el archivo indicado, lo crean nuevo. Por defecto, estas dos clases comienzan a escribir al comienzo del archivo. Para escribir detrás de lo que ya existe en el archivo (“append”), se utiliza un segundo argumento de tipo boolean con valor true:

FileWriter fw = new FileWriter(“archivo.txt”, true);

Las clases que se explican a continuación permiten un manejo más fácil y eficiente.

Clases File y FileDialog

Un objeto de la clase File puede representar un archivo o un directorio. Tiene los siguientes constructores:

File(String name)
File(String dir, String name)
File(File dir, String name).

Se puede dar el nombre de un archivo, el nombre y el directorio, o sólo el directorio, como path absoluto y como path relativo al directorio actual. Para saber si el archivo existe se puede llamar al método boolean exists().

File f1 = new File(“c:\\windows\\notepad.exe”); // La barra ‘\’ se escribe ‘\\’
File f2 = new File(“c:\\windows”); // Un directorio
File f3 = new File(f2, “notepad.exe”); // Es igual a f1

Una forma típica de preguntar por un archivo es presentar una caja de diálogo. La clase java.awt.FileDialog presenta el diálogo típico de cada sistema operativo para guardar o abrir ficheros. Sus constructores son:

FileDialog(Frame fr)
FileDialog(Frame fr, String title)
FileDialog(Frame fr, String title, int type)

donde type puede ser FileDialog.LOAD o FileDialog.SAVE según la operación que se desee realizar.
Es muy fácil conectar este diálogo con un File, utilizando los métodos String getFile() y
String getDirectory(). Por ejemplo:

FileDialog fd = new FileDialog(f, “Elija un archivo”);
fd.show();
File f = new File(fd.getDirectory(), fd.getFile());
ESCRITURA DE ARCHIVOS DE TEXTO

La clase PrintWriter es la más práctica para escribir un archivo de texto porque posee los métodos print(cualquier tipo) y println(cualquier tipo), idénticos a los de System.out (de clase PrintStream).
Un objeto PrintWriter se puede crear a partir de un BufferedWriter (para disponer de buffer), que se crea a partir del FileWriter al que se la pasa el nombre del archivo. Después, escribir en el archivo es tan fácil como en pantalla. El siguiente ejemplo ilustra lo anterior:

try {
FileWriter fw = new FileWriter(“escribeme.txt”);
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter salida = new PrintWriter(bw);
salida.println(“Hola, soy la primera línea”);
salida.close();
// Modo append
bw = new BufferedWriter(new FileWriter(“escribeme.txt”, true));
salida = new PrintWriter(bw);
salida.print(“Y yo soy la segunda. “);
double b = 123.45;
salida.println(b);
salida.close();
}
cacth(java.io.IOException ioex) { }

ARCHIVOS QUE NO SON DE TEXTO

DataInputStream y DataOutputStream son clases de Java 1.0 que no han sido alteradas hasta ahora. Para leer y escribir datos primitivos directamente (sin convertir a/de String) siguen siendo más útiles estas dos clases.
Son clases diseñadas para trabajar de manera conjunta. Una puede leer lo que la otra escribe, que en sí no es algo legible, sino el dato como una secuencia de bytes. Por ello se utilizan para almacenar datos de manera independiente de la plataforma (o para mandarlos por una red entre ordenadores muy distintos).
El problema es que obligan a utilizar clases que descienden de InputStream y OutputStream y por lo tanto algo más complicadas de utilizar. El siguiente código primero escribe en el fichero prueba.dat para después leer los datos escritos:

// Escritura de una variable double
DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream(“prueba.dat”)));
double d1 = 17/7;
dos.writeDouble(d);
dos.close();
// Lectura de la variable double
DataInputStream dis = new DataInputStream(
new BufferedInputStream(
new FileInputStream(“prueba.dat”)));
double d2 = dis.readDouble();

HERENCIA

HERENCIA DE CLASES
La herencia es el mecanismo fundamental de relación entre clases en la orientación a objetos. Relaciona las clases de manera jerárquica; una clase padre o superclase sobre otras clases hijas o subclases.

Los descendientes de una clase heredan todas las variables y métodos que sus ascendientes hayan especificado como heredables, además de crear los suyos propios.
La característica de herencia, nos permite definir nuevas clases derivadas de otra ya existente, que la especializan de alguna manera. Así logramos definir una jerarquía de clases, que se puede mostrar mediante un árbol de herencia.
En todo lenguaje orientado a objetos existe una jerarquía, mediante la que las clases se relacionan en términos de herencia. En Java, el punto más alto de la jerarquía es la clase Object de la cual derivan todas las demás clases.
Herencia múltiple
En la orientación a objetos, se consideran dos tipos de herencia, simple y múltiple. En el caso de la primera, una clase sólo puede derivar de una única superclase. Para el segundo tipo, una clase puede descender de varias superclases.
En Java sólo se dispone de herencia simple, para una mayor sencillez del lenguaje, si bien se compensa de cierta manera la inexistencia de herencia múltiple con un concepto denominado interface, que estudiaremos más adelante.
Declaración
Para indicar que una clase deriva de otra, heredando sus propiedades (métodos y atributos), se usa el término extends, como en el siguiente ejemplo:

public class SubClase extends SuperClase {
// Contenido de la clase
}

Por ejemplo, creamos una clase MiPunto3D, hija de la clase ya mostrada MiPunto:

class MiPunto3D extends MiPunto {
int z;
MiPunto3D( ) {
x = 0; // Heredado de MiPunto
y = 0; // Heredado de MiPunto
z = 0; // Nuevo atributo
}
}

La palabra clave extends se utiliza para decir que deseamos crear una subclase de la clase que es nombrada a continuación, en nuestro caso MiPunto3D es hija de MiPunto.
Limitaciones en la herencia
Todos los campos y métodos de una clase son siempre accesibles para el código de la misma clase.
Para controlar el acceso desde otras clases, y para controlar la herencia por las subclase, los miembros (atributos y métodos) de las clases tienen tres modificadores posibles de control de acceso:
• public: Los miembros declarados public son accesibles en cualquier lugar en que sea accesible la clase, y son heredados por las subclases.
• private: Los miembros declarados private son accesibles sólo en la propia clase.
• protected: Los miembros declarados protected son accesibles sólo para sus subclases
Por ejemplo:
class Padre { // Hereda de Object

// Atributos

private int numeroFavorito, nacidoHace, dineroDisponible;
// Métodos
public int getApuesta() {
return numeroFavorito;
}
protected int getEdad() {
return nacidoHace;
}
private int getSaldo() {
return dineroDisponible;
}
}
class Hija extends Padre {
// Definición
}
class Visita {
// Definición
}

En este ejemplo, un objeto de la clase Hija, hereda los tres atributos (numeroFavorito, nacidoHace y dineroDisponible) y los tres métodos ( getApuesta(), getEdad() y getSaldo() ) de la clase Padre, y podrá invocarlos. Cuando se llame al método getEdad() de un objeto de la clase Hija, se devolverá el valor de la variable de instancia nacidoHace de ese objeto, y no de uno de la clase Padre.
Sin embargo, un objeto de la clase Hija, no podrá invocar al método getSaldo() de un objeto de la clase Padre, con lo que se evita que el Hijo conozca el estado de la cuenta corriente de un Padre.
La clase Visita, solo podrá acceder al método getApuesta(), para averiguar el número favorito de un Padre, pero de ninguna manera podrá conocer ni su saldo, ni su edad (sería una indiscreción, ¿no?).

CLASES ABSTRACTAS
Hay ocasiones, cuando se desarrolla una jerarquía de clases en que algún comportamiento está presente en todas ellas pero se materializa de forma distinta para cada una. Por ejemplo, pensemos en una estructura de clases para manipular figuras geométricas. Podríamos pensar en tener una clase genérica, que podría llamarse FiguraGeometrica y una serie de clases que extienden a la anterior que podrían ser Circulo, Poligono, etc. Podría haber un método dibujar dado que sobre todas las figuras puede llevarse a cabo esta acción, pero las operaciones concretas para llevarla a cabo dependen del tipo de figura en concreto (de su clase). Por otra parte la acción dibujar no tiene sentido para la clase genérica FiguraGeometrica, porque esta clase representa una abstracción del conjunto de figuras posibles.
Para resolver esta problemática Java proporciona las clases y métodos abstractos. Un método abstracto es un método declarado en una clase para el cual esa clase no proporciona la implementación (el código). Una clase abstracta es una clase que tiene al menos un método abstracto. Una clase que extiende a una clase abstracta debe implementar los métodos abstractos (escribir el código) o bien volverlos a declarar como abstractos, con lo que ella misma se convierte también en clase abstracta.
Declaración e implementación de métodos abstractos
Siguiendo con el ejemplo del apartado anterior, se puede escribir:
abstract class FiguraGeometrica {
. . .
abstract void dibujar();
. . .
}

class Circulo extends FiguraGeometrica {
. . .
void dibujar() {
// codigo para dibujar Circulo
. . .
}
}
La clase abstracta se declara simplemente con el modificador abstract en su declaración. Los métodos abstractos se declaran también con el mismo modificador, declarando el método pero sin implementarlo (sin el bloque de código encerrado entre {}). La clase derivada se declara e implementa de forma normal, como cualquier otra. Sin embargo si no declara e implementa los métodos abstractos de la clase base (en el ejemplo el método dibujar) el compilador genera un error indicando que no se han implementado todos los métodos abstractos y que, o bien, se implementan, o bien se declara la clase abstracta.
Referencias y objetos abstractos
Se pueden crear referencias a clases abstractas como cualquier otra. No hay ningún problema en poner:
FiguraGeometrica figura;
Sin embargo una clase abstracta no se puede instanciar, es decir, no se pueden crear objetos de una clase abstracta. El compilador producirá un error si se intenta:
FiguraGeometrica figura = new FiguraGeometrica();
Esto es coherente dado que una clase abstracta no tiene completa su implementación y encaja bien con la idea de que algo abstracto no puede materializarse.
Sin embargo utilizando el up-casting visto en el capítulo dedicado a la Herencia si se puede escribir:
FiguraGeometrica figura = new Circulo(. . .);
figura.dibujar();
La invocación al método dibujarse resolverá en tiempo de ejecución y la JVM llamará al método de la clase adecuada. En nuestro ejemplo se llamará al método dibujarde la clase Circulo.
POLIMORFISMO

El concepto de Polimorfismo es uno de los fundamentos para cualquier lenguaje orientado a Objetos, las mismas raíces de la palabra pueden ser una fuerte pista de su significado: Poli = Multiple, morfismo= Formas , esto implica que un mismo Objeto puede tomar diversas formas.
A través del concepto de Herencias (“Inheritance”) es posible ilustrar este comportamiento:

El poder manipular un Objeto como si éste fuera de un tipo genérico otorga mayor flexibilidad al momento de programar con Objetos, el término Polimorfismo también es asociado con un concepto llamado Late-Binding (Ligamiento Tardío), observe el siguiente fragmento de código:
Figura a = new Circulo();
Figura b = new Triangulo();
Inicialmente se puede pensar que este código generaría un error debido a que el tipo de referencia es distinta a la instancia del objeto, sin embargo, el fragmento anterior es correcto y demuestra el concepto de Polimorfismo; para asentar este tema se describe un ejemplo más completo:

Uso de Polimorfismo .

El uso de Polimorfismo posee ciertos detalles que no fueron descritos en el ejemplo anterior, uno de estos, que también tiene implicaciones en otros componentes es: Casting.

INTRODUCCION

“No te amargues con tu propio fracaso ni se lo cargues a otro, acéptate ahora o seguirás justificándote como un niño, recuerda que cualquier momento es bueno para comenzar y que ninguno es tan terrible para claudicar.”

Después de iniciar con este video de motivación vamos a empezar con una pequeña introducción acerca de los errores de redondeo.

Aunque el bug de Excel 2007 ha tenido mucha cobertura, no es primer error de redondeo de la historia, y tampoco el más catastrófico. Y aunque todavía no sabemos que consecuencas pueda tener este nuevo bug de Excel, por lo menos todavía muere nadie por este error.

Pero durante la primera guerra del golfo hubo un error de similar origen, que le costó la vida a 28 marines norteramericanos.

El origen del bug de excel y del error que mató a los marines es el mismo.

Para los que no lo saben, el error en Excel 2007 consiste en que si ustedes multiplican 77,1 por 850 en vez de obtener 65.535, como debería ser, en la celda se refleja el valor 100.000.

El problema no está en el almacenamiento interno del número, sino que en el despliegue de la cifra en pantalla. Joel Spolsky explica muy bien el error, y sugiero que la lean para ver los detalles.

Pero, en forma breve, tenemos que la representación binaria de 77,1 es la siguiente:

0100 0000 0101 0011 0100 0110 0110 0110
0110 0110 0110 0110 0110 0110 0110 0110

Si se fijan bien la secuencia 0110 0110 0110 se repite. Esto es porque el 0,1 no se puede representar en forma exacta en notación binaria. Es lo mismo que pasa en decimal cuando queremos representar 1/3, que queda 0,333333333333333…..

Esta es una cifra decimal periódica, y tiene infinitos 3 “hacia la derecha”, bueno, lo mismo pasa con el 0,1 en binario. Por eso que hay que tener cuidado cuando se trabaja con números en punto flotante.
Examinemos las consecuencias trágicas de un bug de este tipo.

El 25 de febrero de 1991 una batería de misiles patriot en Dharan, Arabia Saudita, no pudo detener un misil SCUD Iraquí impactando directamente en una barraca con 28 marines.

De acuerdo a un informe oficial sabemos que el misil patriot falló debido a un error acumulado en el cronómetro interno. Resulta que el software usaba un contador que debía incrementarse cada 0,1 segundos para sus cálculos. La batería de misiles patriot llevaba operando 100 horas, lo que acumuló un error de 0,34 segundos, dado que el misil scud se mueve a 1.676 metros por segundo, el misil patriot al ser lanzado ya estaba “desplazado” en casi medio kilómetro del objetivo.

El tipo de error de Excel 2007 y el del misil patriot es de la misma clase, un problema de redondeo, claro que las consecuencias son bien distintas. Sólo esperemos que nadie esté usando Excel 2007 para controlar algún sistema crítico, o del que dependan vidas humanas.

Uno de los problemas que se presenta con mas frecuencia en Ingeniería es encontrar las raíces
de ecuaciones de la forma f(x)= 0; donde f(x) es una función real de una variable x, como un polinomio en x; ejemplo;

f(x)=4x +x + -8x +2

o una función trascendente f(x)= e sen x + ln 3x + x

Existen distintos algoritmos para encontrar las raíces o ceros f(x)= 0, pero ninguno es general , es decir no hay un algoritmo que funcione con todas las ecuaciones.

Sólo en muy pocos casos será posible obtener raíces exactas de f(x) = 0 , como es el caso cuando el polinomio es factorizable ; ejemplo:

f(x)= x – 3x + 2 = 0 = (x – 2)(x-1); las raíces son x= 2 y x= 1;