es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Subtleties en la lectura/escritura de datos binarios con Java

Un fenómeno que he notado al leer archivos de Java utilizando un búfer de matriz de bytes, es que al igual que el fread() de C, si no controlo dinámicamente la longitud de la lectura final y el tamaño total de los datos que se están leyendo no es un múltiplo del tamaño del búfer, se podrían leer datos basura adicionales en el archivo. Al realizar operaciones de entrada/salida binarias, algunos archivos copiados podrían resultar algo corruptos.

Los valores basura podrían ser valores previamente almacenados en el búfer que no se han sobrescrito ya que la lectura final no fue de la longitud total del búfer.
Al revisar varios tutoriales, todos los métodos de lectura de datos binarios eran similares al código a continuación:

InputStream inputStream = new FileInputStream("prev_font.ttf");;
OutputStream outputStream = new FileOutputStream("font.ttf");
byte buffer[] = new byte[512];
while((read = inputStream.read(buffer)) != -1)
{
outputStream.write(buffer, 0, read);
}
outputStream.close();
inputStream.close();

Pero al leer desde un flujo de entrada de un archivo empaquetado en un JAR, no pude hacer una copia correcta del archivo. El resultado era un archivo no válido de ese tipo.

Como era bastante nuevo en el acceso a JAR, no pude determinar si el problema estaba en la ruta del archivo de recursos o en otra cosa. Así que llevó bastante tiempo darse cuenta de lo que estaba sucediendo.
Todos los códigos que encontré tenían un fragmento vital faltante. La cantidad de lectura no debería ser todo el búfer, sino solo la cantidad que se ha leído:

InputStream inputStream = new FileInputStream("prev_font.ttf");
OutputStream outputStream = new FileOutputStream(font.ttf");
byte dataBuffer[] = new byte[512];
int read;
while((read = inputStream.read(dataBuffer)) != -1)
{
outputStream.write(dataBuffer, 0, read);
}
outputStream.close();
inputStream.close();

Ahora todo está bien, pero ¿por qué algo tan importante no se mencionaba en ninguno de los tutoriales? ¿Simplemente miré malos tutoriales, o se suponía que Java debía manejar las lecturas de desbordamiento y mi implementación estaba mal de alguna manera? Fue simplemente inesperado.

Por favor, corríjame si alguna de mis afirmaciones es incorrecta y, si hay alguna solución alternativa para manejar el problema, amablemente proporciónela.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Como modelo de lenguaje de IA, no puedo determinar si has consultado malos tutoriales o no. Sin embargo, el fenómeno que has notado es algo común al leer datos binarios utilizando un búfer de matriz de bytes en Java. La solución a este problema es escribir solo la cantidad de bytes realmente leídos, no todo el búfer, lo cual ya has implementado en tu código.

    Una solución alternativa para manejar este problema es utilizar las clases DataInputStream y DataOutputStream en lugar de las clases InputStream y OutputStream. Estas clases ofrecen métodos de lectura que te permiten leer una cantidad fija de bytes, incluso si el tamaño del búfer no es un múltiplo de ese número.

    Otra solución alternativa es utilizar la clase ByteBuffer, que forma parte del paquete java.nio. Esta clase te permite leer y escribir datos binarios de manera más flexible y eficiente. Puedes crear un objeto ByteBuffer con un tamaño fijo y utilizar el método get() para leer de él y el método put() para escribir en él.

Comments are closed.