1. MARCO TEÓRICO
El almacenamiento de datos en variables y arreglos es temporal; los datos se pierden cuando una variable
local queda fuera de alcance, o cuando el programa termina. Las computadoras utilizan archivos para la
retención a largo plazo de grandes cantidades de datos, incluso hasta después de que terminan los
programas que crean esos datos. Nos referimos a los datos que se mantienen en archivos como datos
persistentes, ya que existen más allá de la duración de la ejecución del programa.
El procesamiento de archivos es una de las herramientas más importantes que debe tener un lenguaje para
soportar las aplicaciones comerciales, que generalmente procesan cantidades masivas de datos persistentes.
El término “flujo” se refiere a los datos ordenados que se leen de (o se escriben en) un archivo.
Jerarquía de datos
Básicamente, una computadora procesa todos los elementos de datos como combinaciones de ceros y unos,
ya que para los ingenieros es sencillo y económico construir dispositivos electrónicos que puedan suponer dos
estados estables: uno representa 0 y el otro, 1. Es increíble que las impresionantes funciones realizadas por
las computadoras impliquen solamente las manipulaciones más fundamentales de 0s y 1s.
El elemento más pequeño de datos en una computadora puede asumir el valor 0 o 1. Dicho elemento de
datos se conoce como bit (abreviatura de “dígito binario”; un dígito que puede suponer uno de dos valores).
Los circuitos de computadora realizan varias manipulaciones simples de bits, como examinar o establecer el
valor de un bit, o invertir su valor (de 1 a 0 o de 0 a 1).
Es muy difícil para los programadores trabajar con datos en el formato de bits de bajo nivel. En vez de ello, los
programadores prefieren trabajar con datos en formatos como dígitos decimales (0-9), letras (A-Z y a-z) y
símbolos especiales (por ejemplo, $, @, %, &, *, (, ), —, +, ", :, ? y / ). Los dígitos, letras y símbolos especiales
se conocen como caracteres. Los caracteres en Java son caracteres Unicode, compuestos de dos bytes.
Cada byte está compuesto de ocho bits.
Así como los caracteres están compuestos de bits, los campos están compuestos de caracteres o bytes. Un
campo es un grupo de caracteres o bytes que transmiten cierto significado. Por ejemplo, un campo que
consiste de letras mayúsculas y minúsculas puede utilizarse para representar el nombre de una persona.
Generalmente, varios campos forman un registro (que se implementa como class en Java), por lo tanto, un
registro es un grupo de campos relacionados. Un archivo es un grupo de registros relacionados. A menudo, a
un grupo de archivos relacionados se le conoce como base de datos.
Archivos y Flujo
Java considera a cada archivo como un flujo secuencial de bytes. Cada sistema operativo proporciona un
mecanismo para determinar el fin de un archivo. En algunos casos, la indicación de fin de archivo ocurre como
una excepción. Un programa de Java abre un archivo creando un objeto y asociándole un flujo de bytes o de
caracteres.
Lenguaje de
programación
Técnica profesional en desarrollo de software
Profesor: Andrés Herrera R. Mail: jherrera@eam.edu.co
Laboratorio
Archivos
Nombre:_________________________________________________________________________
2. 2
Los programas de Java realizan el procesamiento de archivos utilizando clases del paquete java.io. Este
paquete incluye definiciones para las clases de flujo como FileInputStream (para la entrada basada en bytes
desde un archivo), FileOutputStream (para la salida basada en bytes hacia un archivo), FileReader (para la
entrada basada en caracteres desde un archivo) y FileWriter (para la salida basada en caracteres hacia un
archivo). Los archivos se abren creando objetos de estas clases de flujos, que heredan de las clases
InputStream, OutputStream, Reader y Writer, respectivamente.
Java contiene clases que permiten al programador realizar operaciones de entrada y salida con objetos o
variables de tipos de datos primitivos (System.in, System.out y System.err). Los datos se siguen almacenando
como bytes o caracteres tras bambalinas, lo cual permite al programador leer o escribir datos en forma de
enteros, cadenas u otros tipos de datos, sin tener que preocuparse por los detalles acerca de convertir dichos
valores al formato de bytes. Para realizar dichas operaciones de entrada y salida, pueden usarse objetos de
las clases ObjectInputStream, y ObjectOutputStream junto con las clases de flujos de archivos basadas en
bytes FileInputStream y FileOutputStream.
La clase File
En esta sección presentamos la clase File, que es especialmente útil para recuperar información acerca de un
archivo o directorio de un disco. Los objetos de la clase File no abren archivos ni proporcionan herramientas
para procesarlos. No obstante, los objetos File se utilizan frecuentemente con objetos de otras clases de
java.io para especificar los archivos o directorios que van a manipularse.
Creación de objetos file:
Para inicializar un File se debe especificar la ruta del archivo que se desea manejar, las rutas de los archivos
pueden ser absolutas (contiene todos los directorios, empezando con el directorio raíz, que conducen a un
archivo o directorio específico) o relativas (normalmente empieza desde el directorio en el que la aplicación
empezó a ejecutarse y es, por lo tanto, una ruta “relativa” al directorio actual). El objeto File posee cuatro
métodos constructores en los cuales siempre se debe contar con la ruta del archivo. A continuación en la
Tabla 1 se enuncian algunos de los métodos que ofrece la clase File.
Nombre método Descripción
boolean canRead() Devuelve true si la aplicación actual puede leer un
archivo; false en caso contrario.
boolean canWrite() Devuelve true si la aplicación actual puede escribir
en un archivo; false en caso contrario.
boolean exists() Devuelve true si el nombre especificado como
argumento para el constructor de File es un archivo
o directorio en la ruta especificada; false en caso
contrario.
boolean isDirectory() Devuelve true si el nombre especificado como
argumento para el constructor de File es un
directorio; false en caso contrario.
boolean isAbsolute() Devuelve true si los argumentos especificados para
el constructor de File indican una ruta absoluta a un
archivo o directorio; false en caso contrario.
String getAbsolutePath() Devuelve una cadena con la ruta absoluta del
archivo o directorio. String getName() Devuelve una
cadena con el nombre del archivo o directorio.
3. 3
String getPath() Devuelve una cadena con la ruta del archivo o
directorio.
String getParent() Devuelve una cadena con el directorio padre del
archivo o directorio (es decir, el directorio en el que
puede encontrarse ese archivo o directorio).
long length() Devuelve la longitud del archivo, en bytes. Si el
objeto File representa a un directorio, se devuelve
0.
long lastModified() Devuelve una representación dependiente de la
plataforma de la hora en la que se hizo la última
modificación en el archivo o directorio. El valor
devuelto es útil sólo para compararlo con otros
valores devueltos por este método.
String[] list() Devuelve un arreglo de cadenas, las cuales
representan el contenido de un directorio. Devuelve
null si el objeto File no representa a un directorio.
Tabla 1. Listado de métodos de la clase File.
Las operaciones realizadas con archivos pueden realizarse de varias formas, para disminuir la curva de
aprendizaje se usará la clase Formatter de Java. Esta clase es usada regularmente para dar formato a las
cadenas de texto compuestas por diferentes tipos de datos.
PRACTICA
1- Cree un proyecto de nombre <<Archivos>>.
2- Cree un paquete de nombre <<com.EAM.lenguaje.archivos>>.
3- Cree los paquetes <<txt>> y <<vo>> dentro del paquete creado en el punto anterior.
4- Cree un archivo sin extensión dentro del proyecto y nómbrelo <<prueba>>.
5- Cree en el paquete txt una clase de nombre <<PruebaClaseFile>> con su respectivo método main y agregue el siguiente
código:
public static void analizarArchivo(String ruta) {
File file = new File(ruta);
if (file.exists()) {
System.out.printf("Nombre: %s n Es archivo? %s n Es directorio? %s n Es una ruta
absoluta? %s n Ultima modificación: %s n Ruta: %s n Ruta absoluta: %s n", file.getName(),
file.isFile(),
file.isDirectory(), file.isAbsolute(), file.lastModified(),
file.getPath(), file.getAbsolutePath());
if( file.isDirectory() ){
String directorios [] = file.list();
System.out.println("El contenido es:");
for (int i = 0; i < directorios.length; i++)
System.out.printf("%sn", directorios[i]);
}
4. 4
}
else{
System.out.println("El archivo no existe");
}
}
Revise el código y analice su funcionamiento.
6- Use el método anterior para manejar la información del archivo prueba usando rutas <<absolutas>> y <<relativas>>
(consulte al profesor en que consisten las rutas absolutas y relativas). ¿Qué tipo de rutas debe usar un buen programador?
7- Cree en el paquete <<vo>> la clase <<GrupoMusical>> en el mismo proyecto. Agregue en esta clase los siguientes
atributos: identificación (String), nombre (String), genero (String), antigüedad (int). Cree un método constructor que reciba
todos los parámetros y los inicialice. Además sobreescriba el método toString.
8- Cree en el paquete <<txt>> la clase <<ManagerArchivo>>. Agregue un atributo de clase de nombre archivo y tipo
<<Formatter>>. Agregue el siguiente código en esta clase:
public void abrirArchivo(){
try {
archivo = new Formatter("info.txt");
System.out.println("conexión abierta");
} catch (FileNotFoundException fileNotFoundException) {
fileNotFoundException.printStackTrace();
}
catch (SecurityException securityException) {
securityException.fillInStackTrace();
}
}
Cuando se inicializa el atributo archivo se crea una conexión con “info.txt”. La primera vez que se ejecuta esta línea se crea
el archivo “info.txt”.
Programe el método constructor y llame al método <<abrirArchivo>>.
9- Agregue el siguiente método dentro de la clase ManagerArchivo:
public void cerrarArchivo(){
if(archivo != null){
archivo.close();
System.out.println("conexión cerrada");
}
}
Toda conexión que se abre con cualquier tipo de archivo se debe cerrar.
10- Agregue el siguiente método dentro de la clase ManagerArchivo:
public void crearGrupoMusical(){
try(Scanner scanner = new Scanner(System.in); GrupoMusical grupoMusical= new
GrupoMusical()){
5. 5
System.out.println("Ingrese el id");
while (scanner.hasNext()) {
grupoMusical.setId(scanner.next());
System.out.println("Ingrese el nombre");
grupoMusical.setNombre(scanner.next());
System.out.println("Ingrese el genero");
grupoMusical.setGenero(scanner.next());
System.out.println("Ingrese la antiguedad");
grupoMusical.setAntiguedad(scanner.nextInt());
archivo.format("%s %s %s %dn", gM.getId(),gM.getNombre(), gM.getGenero(),
gM.getAntiguedad());
System.out.println("Ingrese el id");
}
}
catch (FormatterClosedException formatterClosedException) {
System.err.println("Error al escribir en el archivo.");
return;
} catch (NoSuchElementException elementException) {
System.err.println("Entrada invalida. Intente de nuevo.");
} catch (IOException e) {
e.printStackTrace();
}
}
Como se puede notar la única línea necesaria para escribir en un archivo es la que llama al método <<format>>.
11- Programe una clase de nombre <<PruebaTXT>> y pruebe los desarrollado en los puntos anteriores.
12- Cree como atributo de clase una variable de nombre entrada tipo Scanner. En la clase ManagerArchivo agregue el
siguiente código:
public void abrirArchivoScanner(){
try {
entrada= new Scanner(new File("info.txt"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
Con el anterior código se podrá realizar una conexión con el archivo info.txt, y simplemente se tendrá que recorrer el
Scanner para obtener la información.
13- Agregue los dos siguientes métodos y compréndalos:
public void cargarGruposMusicales(){
try(GrupoMusical grupoMusical= new GrupoMusical()){
while (entrada.hasNext()) {