¿Qué es InputStream en Java y cómo se utiliza en la lectura de datos?

| Última modificación: 2 de diciembre de 2024 | Tiempo de Lectura: 3 minutos

Algunos de nuestros reconocimientos:

Premios KeepCoding

¿Qué harías si te dijera que puedes tener un control muy preciso sobre cómo y cuándo se leen los datos en tu aplicación? Sería grandioso, ¿no? Pues con InputStream en Java es totalmente posible. Te deja leer datos desde diferentes fuentes, como archivos, redes o dispositivos, todo a nivel de bytes. Además, es muy útil para trabajar con archivos binarios o flujos de datos no estructurados y es la base para otras implementaciones que también optimizan la lectura, como FileInputStream y BufferesInputStream. Te cuento más sobre cómo usarlo en la lectura de datos.

InputStream en Java esquema

¿Qué es InputStream en Java?

InputStream es una clase abstracta en Java que forma parte del paquete java.io. Con esta clase se leen los datos byte por byte desde un flujo de entrada, como un archivo, un socket de red o incluso la entrada estándar (como el teclado). Dado que es una clase abstracta, no puedes crear instancias directamente de InputStream, pero sí puedes usar sus clases derivadas, como FileInputStream, para leer datos de manera más específica.

Los métodos más importantes de InputStream en Java

Como te dije, es una clase abstracta, por eso InputStream en Java proporciona varios métodos que las clases que la implementan deben definir.

Estos son los más comunes:

  • int read(): Lee un solo byte del flujo de entrada. Si no hay más datos por leer, devuelve -1.
  • int read(byte[] bytes): Lee un número de bytes igual o menor que el tamaño del arreglo bytes que le pases como argumento.
  • int read(byte[] bytes, int start, int n): Similar al anterior, pero te permite especificar el índice desde el que empezar a escribir en el arreglo y cuántos bytes leer.
  • void close(): Cierra el flujo de entrada y libera los recursos asociados.
  • int available(): Retorna el número de bytes que pueden ser leídos desde el flujo sin bloquearse. Es útil cuando quieres saber cuántos bytes quedan por leer sin necesidad de hacer una lectura completa.

¿Cómo utilizar InputStream en Java?

Con este ejemplo práctico que te dejo aquí, pretendo que aprendas a programar con Java usando esta clase que te trae tantos beneficios. En este ejemplo lo usarás para leer un archivo byte por byte.

Ejemplo práctico: Leer un archivo con InputStream en Java

Imagina que tienes un archivo llamado ejemplo.txt y quieres leer su contenido byte por byte. Para hacerlo, puedes utilizar FileInputStream, que es una clase derivada de InputStream:

import java.io.*;

public class LeerArchivo {
public static void main(String[] args) {
try {
// Creamos un objeto FileInputStream para leer el archivo
FileInputStream archivo = new FileInputStream("ejemplo.txt");

// Leemos el archivo byte por byte
int byteLeido;
while ((byteLeido = archivo.read()) != -1) {
// Procesamos cada byte leído
System.out.print((char) byteLeido); // Convertimos el byte a char y lo mostramos
}

// Cerramos el archivo
archivo.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

Aquí, el método read() de InputStream se usó para leer un byte a la vez. Si notaste bien, cuando no quedan más bytes por leer, read() devuelve -1 y el bucle termina. En este caso, cada byte leído se convierte en un carácter y se imprime en la consola.

Leer grandes bloques de datos

Si estás trabajando con archivos grandes y necesitas optimizar la lectura, puedes usar un arreglo de bytes para leer varios bytes a la vez. Aquí tienes un ejemplo:

import java.io.*;

public class LeerArchivoConBuffer {
public static void main(String[] args) {
try {
FileInputStream archivo = new FileInputStream("archivoGrande.txt");

byte[] buffer = new byte[1024]; // Un arreglo para almacenar hasta 1024 bytes a la vez
int bytesLeidos;
while ((bytesLeidos = archivo.read(buffer)) != -1) {
// Procesamos los bytes leídos
System.out.write(buffer, 0, bytesLeidos); // Escribimos los bytes leídos
}

archivo.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

En este caso, el arreglo buffer fue usado para almacenar hasta 1024 bytes a la vez, y mejorar así la eficiencia al leer grandes archivos. También pudiste notar que, el método read(byte[] bytes) es más rápido que leer byte por byte, porque reduce la cantidad de operaciones de lectura.

BufferedInputStream para mejorar el rendimiento

También es posible que optimices aún más el rendimiento al leer grandes archivos, solo debes envolver tu FileInputStream con un BufferedInputStream. Así se leerán más datos de una sola vez en lugar de hacer muchas lecturas pequeñas.

Mira el mismo ejemplo, pero utilizando BufferedInputStream:

import java.io.*;

public class LeerConBufferedInputStream {
public static void main(String[] args) {
try {
BufferedInputStream archivo = new BufferedInputStream(new FileInputStream("archivoGrande.txt"));

byte[] buffer = new byte[1024];
int bytesLeidos;
while ((bytesLeidos = archivo.read(buffer)) != -1) {
System.out.write(buffer, 0, bytesLeidos);
}

archivo.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

Como ves, BufferedInputStream lee bloques grandes de datos y luego los procesa, así es como mejora la eficiencia al reducir el número de lecturas directas del archivo.

No te quedes solo con la teoría, puedes profundizar más en Java si te unes al Bootcamp de Java Full Stack de KeepCoding! Aquí aprenderás todo lo que necesitas saber para convertirte en un experto en Java y empezarás a trabajar en proyectos reales que te prepararán para una carrera exitosa en el mundo IT. ¡Inscríbete ahora mismo!

Ramón Maldonado

Full Stack Developer y Responsable de Formación base en KeepCoding.

Posts más leídos

¡CONVOCATORIA ABIERTA!

Java y Spring Boot

Full Stack Bootcamp

Clases en Directo | Profesores en Activo | Temario 100% actualizado