CodeGym /Blog Java /Random-ES /Entrada/salida en Java. Clases FileInputStream, FileOutpu...
Autor
Alex Vypirailenko
Java Developer at Toshiba Global Commerce Solutions

Entrada/salida en Java. Clases FileInputStream, FileOutputStream y BufferedInputStream

Publicado en el grupo Random-ES
"¡Hola! En la lección de hoy, continuaremos nuestra conversación sobre flujos de entrada y salida en Java ( Java I/O ). Esta no es la primera lección sobre este tema, y ​​ciertamente no será la última :) Entrada/salida en Java.  Clases FileInputStream, FileOutputStream y BufferedInputStream - 1Como sucede, el lenguaje Java proporciona muchas formas de trabajar con E / S. Hay bastantes clases que implementan esta funcionalidad, por lo que las hemos dividido en varias lecciones, para que no se confunda desde el principio :) En el pasado lecciones, mencionamos BufferedReader, así como las InputStreamclases OutputStreamabstractas y varias descendientes. Hoy consideraremos 3 nuevas clases: FileInputStream,  FileOutputStreamy  BufferedInputStream.

La clase FileOutputStream

El objetivo principal de la FileOutputStreamclase es escribir bytes en un archivo. Nada complicado :) FileOutputStreames una de las implementaciones de la OutputStreamclase abstracta. En el constructor, los objetos de esta clase toman la ruta al archivo de destino (donde se deben escribir los bytes) o un Fileobjeto. Examinaremos ejemplos de cada uno:

public class Main { 

   public static void main(String[] args) throws IOException { 

       File file = new File("C:\\Users\\Username\\Desktop\\test.txt"); 
       FileOutputStream fileOutputStream = new FileOutputStream(file); 

       String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!"; 

       fileOutputStream.write(greetings.getBytes()); 
       fileOutputStream.close(); 
   } 
}
Al crear el Fileobjeto, pasamos la ruta deseada al constructor. No necesitamos crearlo previamente: si no existe, el programa lo creará. También puede arreglárselas sin crear un objeto adicional, simplemente pasando una cadena con la ruta:

public class Main { 

    public static void main(String[] args) throws IOException { 

       FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt"); 
       String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!"; 

       fileOutputStream.write(greetings.getBytes()); 
       fileOutputStream.close(); 
   } 
} 
El resultado en ambos casos será el mismo. Podemos abrir nuestro archivo y ver allí lo siguiente:

Hi! Welcome to CodeGym — The best site for would-be programmers!
Pero hay un matiz aquí. Intente ejecutar el código del ejemplo anterior varias veces seguidas. Luego busque en el archivo y responda esta pregunta: ¿cuántas líneas tiene? Solo uno. Pero ejecutó el código varias veces. Resulta que los datos se sobrescriben cada vez: lo antiguo se reemplaza por lo nuevo. ¿Qué hacemos si eso no nos conviene y necesitamos escribir secuencialmente en el archivo? ¿Qué pasa si queremos escribir nuestro saludo en un archivo tres veces seguidas? Es todo muy simple. Dado que el lenguaje no puede saber qué comportamiento necesitamos en cada caso, el FileOutputStreamconstructor puede tomar un parámetro adicional:boolean append. Si su valor es verdadero, los datos se escribirán al final del archivo. Si es falso (y por defecto es falso), los datos antiguos se borrarán y se reemplazarán por datos nuevos. Verifiquemos esto ejecutando nuestro código modificado tres veces:

public class Main { 

   public static void main(String[] args) throws IOException { 

       FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt", true); 
       String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!\r\n"; 

       fileOutputStream.write(greetings.getBytes()); 
       fileOutputStream.close(); 
   } 
} 
Contenido del archivo:

Hi! Welcome to CodeGym — The best site for would-be programmers! 
Hi! Welcome to CodeGym — The best site for would-be programmers! 
Hi! Welcome to CodeGym — The best site for would-be programmers!
¡Ahora eso es diferente! No olvide esta función cuando utilice clases de E/S. Hubo un tiempo en el que pasaba horas en tareas, devanándome los sesos durante horas, tratando de entender cómo desaparecían mis datos de los archivos :) Y, por supuesto, al igual que con otras clases de E/S, no olvides usar el close()método para liberar recursos.

La clase FileInputStream

tiene FileInputStreamel propósito opuesto: leer bytes de un archivo. Así como FileOutputStreamhereda OutputStream, esta clase se deriva de la InputStreamclase abstracta. Escribiremos unas pocas líneas de texto en nuestro archivo " test.txt ":

"So close no matter how far 
Couldn't be much more from the heart 
Forever trusting who we are 
And nothing else matters"
Entrada/salida en Java.  Clases FileInputStream, FileOutputStream y BufferedInputStream - 2Aquí lo que parece leer datos de un archivo usando FileInputStream:

public class Main { 

   public static void main(String[] args) throws IOException { 

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\test.txt"); 

       int i; 

       while((i=fileInputStream.read())!= -1){ 

           System.out.print((char)i); 

       } 
   } 
}
Leemos un byte del archivo, convertimos los bytes leídos en caracteres y los mostramos en la consola. Y aquí está la salida de la consola:

So close no matter how far 
Couldn't be much more from the heart 
Forever trusting who we are 
And nothing else matters

La clase BufferedInputStream

Creo que, dado el conocimiento de lecciones anteriores, puede decir fácilmente por qué necesitamos la BufferedInputStreamclase y qué ventajas tiene en comparación con FileInputStream:) Ya hemos encontrado flujos almacenados en búfer, así que intente adivinar (o recordar) antes de continuar leyendo :) Los flujos almacenados en búfer se necesitan principalmente para optimizar la E/S. Acceder a una fuente de datos, como leer un archivo, es una operación costosa en términos de rendimiento. Y acceder a un archivo para leer cada byte es un desperdicio. Es por eso que BufferedInputStreamlee los datos no un byte a la vez, sino en bloques, y los almacena temporalmente en un búfer especial. Esto nos permite optimizar el programa al reducir el número de veces que accedemos al archivo. Veamos cómo se ve esto:

public class Main { 

   public static void main(String[] args) throws IOException { 

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\test.txt"); 

       BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream, 200); 

       int i; 

       while((i = bufferedInputStream.read())!= -1){ 

           System.out.print((char)i); 
       } 
   } 
} 
Aquí creamos un BufferedInputStreamobjeto. Su constructor toma una instancia de la InputStreamclase o cualquiera de sus descendientes, así FileInputStreamlo hará. Como argumento adicional, toma el tamaño del búfer en bytes. Gracias a este argumento, los datos ahora se leerán del archivo no un byte a la vez, ¡sino 200 bytes a la vez! Imagine cuánto hemos reducido el número de accesos a archivos. Para comparar el rendimiento, puede tomar un archivo de texto grande (varios megabytes de texto) y comparar el tiempo en milisegundos que tarda en leerse y enviarse a la consola usando FileInputStreamy BufferedInputStream. Aquí hay un código que demuestra ambas opciones:

public class Main { 

   public static void main(String[] args) throws IOException { 

       Date date = new Date(); 

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\textBook.rtf"); 
       BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream); 

       int i; 
       while((i = bufferedInputStream.read())!= -1){ 

           System.out.print((char)i); 
       } 

       Date date1 = new Date(); 
       System.out.println((date1.getTime() - date.getTime())); 
   } 
} 

 
public class Main { 

   public static void main(String[] args) throws IOException { 

       Date date = new Date(); 
       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\26951280.rtf"); 

       int i; 
       while((i = fileInputStream.read())!= -1){ 

           System.out.print((char)i); 
       } 


       Date date1 = new Date(); 
       System.out.println((date1.getTime() - date.getTime())); 
   }
}
Al leer un archivo de 1,5 MB en mi computadora, FileInputStreamcompleté el trabajo en ~3500 milisegundos, pero BufferedInputStreamlo logré en ~1700 milisegundos. Como puede ver, la transmisión almacenada en búfer optimizó el trabajo, ¡reduciéndolo a la mitad! :) Continuaremos estudiando las clases de I/O — ¡hasta pronto!
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION