No es un bug, es una característica no documentada

domingo, 4 de octubre de 2015

Acceso a datos. Manejo de ficheros

22:58 Posted by Inazio , No comments

Tema 1. Manejo de ficheros


Entrada / salida estándar


Para la entrada y salida estándar tenemos varias clases que podemos emplear.

è Clase java.lang.System
·         System.in implementa la entrada estándar
·         System.out implementa la salida estándar
·         System.err implementa la salida de error

Éstas clases se implementan con el paquete java.io.

è System.out
·         Instancia de la clase PrintStream – flujo de bytes de salida
·         Métodos de utilidad – impresión de datos
§  print(), println()
§  flush() vacía el buffer de salida escribiendo su contenido
è System.in
·         Instancia de la clase InputStream – flujo de bytes de entrada
·         Métodos
§  read() permite leer un caracter
§  skip(n) ignora n caracteres siguientes de la entrada
§  available() número de caracteres disponibles para leer en la trada
è System.err
·         Funcionamiento similar a System.out

Veamos un par de códigos de ejemplo:

Ejemplo 1:
import java.io.*;

class CuentaCaracteres {

     public static void main(String args[]) throw IOException{
          int contador = 0;
          while(System.in.read() != '\n')
                contador++;
          System.out.println();
          System.out.println("Tecleados: " + contador + " caracteres");
     }
}

Ejemplo 2:
import java.io.*;
import java.util.Scanner;

class CuentaCaracteres2{
     public static void main(String args[]) throws IOException{
          Scanner sc = new Scanner(System.in);
          System.out.println("Introduzca una cadena");
          String teclado = sc.nextLine();
          System.out.println("Teclados " + teclado.length() + " caracteres");
     }
}

Streams


Un stream representa un flujo de información, una secuencia ordenada de datos procedente de una fuente (teclado, file, memoria, red, etc.) o dirigida a un destino (pantalla, file, etc).

Los streams comparten una misma interfaz que hace abstracción de los detalles específicos de cada dispositivo de E/S.

Todas las clases de streams están en el paquete java.io.




Hay varios tipos de Streams:

Representación de la información
è Flujos de bytes
è Flujos de caracteres

Propósito
è Entrada – (InputStream, Reader)
è Salida – (OutputStream, Writer)
è Entrada / Salida – (RandomAccessFile)

Acceso
è Secuencial
è Directo o aleatorio – (RandomAccessFile)

Por operación
è Transferencia de datos
è Transformación de los datos (Realizan algún tipo de procesamiento sobre los datos, por ejemplo buffering, conversiones, filtrados…)

Cada Stream define la entrada / salida en términos de streams
Un stream es una secuencia ordenada de datos.

Tienen:
è Una fuente = streams de entrada
è Un destino = streams de salida

El paquete java.io tiene dos partes principales:
è Stream de caracteres (caracteres Unicode de 16 bits)
è Stream de bytes (8 bits)

Paquete java.io


E/S puede estar basada en:
è Texto. Streams de caracteres legibles. Por ejemplo el código fuente de un programa
è Datos. Streams de datos binarios. Por ejemplo el patrón de bits de una imagen.

Los streams de caracteres se utilizan en la E/S basada en texto. Se denominan lectores (reader) y escritores (writer).

Los streams de bytes se utilizan en la E/S basada en datos. Se denominan streams de entrada y streams de salida.

Clases principales


Clases de flujo de entrada.
Se utilizan para leer datos de una fuente de entrada (archivo, cadena o memoria).
è  Flujo de bytes: InputStream, BufferedInputStream, DataInputStream, FileInputStream.
è Flujo de caracteres: Reader, BufferReader, FileReader.

Clases de flujo de salida.
Son las homogéneas a las clases de flujo de entrada y se utilizan para enviar flujos de datos a dispositivos de salida.
è Flujo de bytes: OutputStream, PrintStream, BufferedOutputStream, DataOutputStream y FileOutputStream.
è Flujo de caracteres: Writer, PrintWriter, FileWriter

Clases de archivo:
File y RandomAccessFile que permiten mayor control sobre los archivos.

Jerarquía parcial de clases





InputStream



OutputStream



Streams sobre ficheros


FileInputStream. Muy similar a la clase InputStream, sólo que está diseñada para leer archivos.
è FileInputStream(String name)
è FileInputStream(File name)

FileOutputStream. Muy similar a la clases OutputStream, sólo que está diseñada para escribir en archivos.
è FileOutputStream(String name)
è FileOutputStream(String name, boolean append)
·         Si append = true queremos añadir al final del fichero
è FileOutputStream(File name)

Esquema de trabajo



Ejemplos:

Lectura de byte

import java.io.*;

public class EjemploLecturaByte{
     public static void main(String[] args){
    
          FileInputStream fis = null;
          int aux = 0;
          try{
                fis = new FileInputStream("C:\\eclipse\\readme\\readme_eclipse.html");
                while((aux = fis.read()) != -1)
                     System.out.println(aux + " - " + (char)aux);
          }
          catch(FileNotFoundException e){
                e.printStackTrace();
          }
          catch(IOException e){
                e.printStackTrace();
          }
          finally{
                try{
                     fis.close();
                }
                catch(IOException e){
                     e.printStackTrace();
                }
          }
     }
}

Escritura de byte

import java.io.*;

public class EjemploEscrituraByte{
     public static void main(String[] args){
    
          FileOutputStream fos = null;
          int aux = 0;
          try{
                fos = new FileOutputStream("D:\\Prueba.txt");
                fos.write(67); fos.write(76); fos.write(67); fos.write(32);
          }
          catch(FileNotFoundException e){
                e.printStackTrace();
          }
          catch(IOException e){
                e.printStackTrace();
          }
          finally{
                try{
                     fos.close();
                }
                catch(IOException e){
                     e.printStackTrace();
               }
          }
     }
}

Flujo con Array

import java.io.*;

public class EjemploFlujoArray{
     public static void main(String[] args) throws IOException{
          byte[] byteArr1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
          ByteArrayInputStream flujoArrByte1 = new ByteArrayInputStream(byteArr1);
          while(flujoArrByte1.available() != 0){
                byte leido = (byte) flujoArrByte1.read();
                System.out.println(leido);
          }
          flujoArrByte1.close();
     }
}

Streams sobre ficheros

import java.io.*;

public class Copia{
     public static void main(String[] args){
          FileInputStream origen = null;
          FileOutputStream destino = null;
         
          try{
                origen = FileInputStream(args[0]);
                destino = new FileOutputStream(args[1], true); // añadir
                int i = origen.read();
                while(i != -1){ // Mientras no EOF
                     destino.write(i);
                     i = origen.read();
                }
                origen.close();
                destino.close();
          }
          catch(IOException e){
                System.out.println("Error de ficheros");
          }
     }
}

FileReader



FileWriter




Ejemplos:


Lectura de char

import java.io.*;

public class EjemploLecturaChar{
     public static void main(String[] args){
          FileReader fr = null;
          int aux = 0;
         
          try{
                fr = new FileReader("C:\\eclipse\\readme\\readme_eclipse.html");
                while((aux = fr.read()) != -1)
                     System.out.println((char)aux);
          }
          catch(FileNotFoundException e){
                e.printStackTrace();
          }
          catch(IOException e){
                e.printStackTrace();
          }
          finally{
                try{
                     fr.close();
                }
                catch(IOException e){
                     e.printStackTrace();
                }
          }
     }
}

Escritura de char

import java.io.*;

public class EjemploEscrituraChar{
     public static void main(String[] args){
          FileWriter fw = null;
         
          try{
                fw = new FileWriter("D:\\Prueba.txt");
                fw.write('A');fw.write('A');fw.write(' ');fw.write('d');fw.write('S');fw.write('1');
          }
          catch(FileNotFoundException e){
                e.printStackTrace();
          }
          catch(IOException e){
                e.printStackTrace();
          }
          finally{
                try{
                     fw.close();
                }
                catch(IOException e){
                     e.printStackTrace();
               }
          }
     }
}

Reader y Writer


Sirve para dar soporte Unicode en todas las operaciones de E/S

En ocasiones hay que combinar streams de caracteres y de bytes:
è InputStreamReader convierte un InputStream en un Reader
è OutputStream convierte un OutputStream en un Writer

Casi todas las clases de la jerarquía de streams de bytes tienen su correspondiente clase Reader o Writer con interfaces casi idénticas.

BufferedReader y BufferedWriter sirven como almacenamiento temporal en un buffer, para no actuar directamente sobre el stream.

Igual que los streams de bytes se deben cerrar explícitamente para liberar sus recursos asociados (close).

Ejemplo

import java.io.*;

public class EjemploFiltro{
     public static void main(String[] args){
          String nombreArchivo = "D:\\prueba.txt";
          FileReader fr;
          BufferedReader filtro;
          String linea;
         
          try{
                fr = new FileReader(nombreArchivo);
                filtro = new BufferedReader(fr);
                linea = filtro.readLine();
                while(linea != null){
                     System.out.println(linea);
                     linea = filtro.readLine();
                }
                filtro.close();
                fr.close();
          }
          catch(IOException e){
                System.out.println("No se puede abrir el archivo para lectura");
          }
     }
}

Ejemplo aplicado. Filtro para encriptar

import java.io.*;

public class EncriptadoStream extends FilterOutputStream{
    
     public EncriptadorStream(OutputStream out){
          super(out);
     }
    
     public void write(int b) throws IOException{
          if (b == 255)
                b = 0;
          else
                b++;
          out.write(b);
     }
    
     public static void main(String[] args){
          // Test
          FileInputStream entrada = new FileInputStream("D:\\entrada.txt");
          EncriptadorStream salida = new EncriptadorStream(new FileOutputStream("D:\\salida.txt"));
          while (entrada.available() > 0)
                salida.write(entrada.read());
          entrada.close();
          salida.close();
     }
}

Entrada desde teclado

import java.io.*;

public class EntradaTeclado{
    
     public static void main(String[] args) throws IOException{
    
          InputStreamReader isr;
          BufferedReader teclado;
          String linea;
          byte b;
          int i;
          double d;
          boolean leido;
         
          isr = new InputStreamReader(System.in);
          teclado = new BufferedReader(isr);
         
          System.out.print("Introduzca un byte");
          linea = teclado.readLine();
          b = Byte.parseByte(linea);
          System.out.println("Byte introducido: " + b);
         
          System.out.print("Introduzca un entero");
          linea = teclado.readLine();
          i = Integer.parseInt(linea);
          System.out.println("Entero introducido: " + i);
         
          System.out.print("Introduzca un real");
          linea = teclado.readLine();
          d = Double.parseDouble(linea);
          System.out.println("Real introducido: " + d);
         
          do{
                try{
                     System.out.print("Introduzca un entero:");
                     linea = teclado.readLine();
                     i = Integer.parseInt(linea);
                     leido = true;
                }
                catch(NumberFormatException e){
                     System.out.println("Entero no correcto, inténtelo de nuevo");
                     leido = false;
                }
          }while(!leido);
          System.out.println("Entero introducido: " + i);
     }
}

Lectura del teclado


BufferedReader teclado = new BufferedReader(new InputStreamReader(System.in));
String entrada = teclado.readLine();

Escribir en fichero


FileOutputStream fos = new FileOutputStream("fichero.txt");
PrintWriter pr = new PrintWriter(fos);
...
pr.println("Escribimos texto");

Ejemplo

import java.io.*;

public class EscribirFichero{
     public static void main(String[] args){
          try{
                FileOutputStream fos = new FileOutputStream("salida.txt");
                PrintWriter pw = new PrintWriter(fos);
                pw.println("Escribimos una cadena y un entero" + 5);
                pw.flush();
                pw.close();
                fos.close();
          }
          catch(FileNotFoundException e){
                e.printStackTrace();
          }
          catch(IOException e){
                e.printStackTrace();
          }
    
}

La clase PrintWriter, que también deriva de Writer, posee los métodos print(String) y println(String), idénticos a los de System.out. Recibe un String y lo imprimen en un fichero, el segundo con salto de línea.



FileWriter fw = new FileWriter("fichero.txt");
PrintWriter pr = new PrintWriter(fos);
...
pr.println("Escribimos texto");

Lectura de líneas



FileInputStream fis = new FileInputStream("fichero.txt");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader buffer = new BufferedReader(isr);
...
String linea = buffer.readLine();

Ejemplo

import java.io.*;

public class LectorFichero{
     public static void main(String[] args){
          byte[] buffer = new byte[80];
          try{
                FileInputStream fichero = new FileInputStream("Leeme.txt");
                int i = fichero.read(buffer);
                String s = new String(buffer);
                System.out.println(s);
          }
          catch(FileNotFoundException e){
                e.printStackTrace();
          }
          catch(IOException e){
                e.printStackTrace();
          }
     }
}

Podemos cambiar FileInputStream por FileReader en cuyo caso el buffer sería un char[].

Leer de fichero



FileReader fr = new FileReader("fichero.txt");
BufferedReader buffer = new BufferedReader(fr);
...
String linea = buffer.readLine();

Clases DataInputStream y DataOutputStream


Permiten transmitir tipos primitivos por un stream


Escritura en modo datos




FileOutputStream fos = new FileOutputStream("salida.dat");
DataOutputStream dos = new DataOutputStream(fos);
dos.writeInt(5);

Lectura en modo datos



0 comentarios:

Publicar un comentario