¿Existe algún peligro al escribir bytes en bruto en un archivo? [cerrado]

12

Estoy trabajando en un problema en Programming Pearls, específicamente, la implementación de un programa que ordena un archivo que contiene, como máximo, 10,000,000 enteros (Columna 1, Problema 3). Dado que el libro no especifica cómo deben almacenarse los datos en el archivo, estoy considerando almacenar los enteros como bytes sin procesar (hay otras restricciones que hacen que los bytes en bruto sean una buena opción). Nunca antes había trabajado a un nivel tan bajo, así que quiero saber si hay algo peligroso que deba vigilar. ¿Debo preocuparme por el uso accidental de algún tipo de secuencia de final de archivo cuando escribo bytes sin procesar en un archivo, por ejemplo?

Editar:

Ahora me doy cuenta de lo amplia que era mi pregunta. Realmente quise decir problemas del tipo más catastrófico, como sobrescribir accidentalmente otros archivos en el disco. Lo siento, no estaba más claro originalmente.

    
pregunta Drake Sobania 27.08.2014 - 19:41

4 respuestas

11

El único peligro con el que se encontrará es pequeño frente a gran endianess (ya se escriba primero el byte más significativo o el menos significativo). Sin embargo, si permanece en el mismo entorno, no habrá ningún problema. además de la garantía general de escribir / analizar ida y vuelta.

El sistema de archivos está diseñado para manejar cualquier secuencia de bytes.

    
respondido por el ratchet freak 27.08.2014 - 19:49
27

No, de hecho, esta es la cantidad de formatos de archivo que funcionan. Los ejemplos comunes de archivos binarios como este incluyen imágenes y archivos de música / audio.

Para mantener la integridad del archivo y los datos leídos, asegúrese de seguir estas pautas:

  • Siempre abra el archivo (lectura o escritura) usando el mismo modo: texto o binario. La principal diferencia es que el modo de texto se preocupa por las nuevas líneas, y puede "rechazar" los caracteres de las nuevas líneas al leer un archivo (dependiendo de la biblioteca específica que se use). El modo de texto también puede realizar traducciones de Unicode que probablemente se atascarán con datos que no sean de Unicode.
  • Al leer datos sin cadenas, asegúrese de leer con el mismo tipo de datos que escribe. Por ejemplo, si los primeros cuatro bytes del archivo son un número entero descriptivo, asegúrese de leer y escribir usando un método que tome / proporcione un número entero para asegurarse de que se trate de manera consistente. El mismo tipo de datos puede tener un tamaño diferente en máquinas diferentes, y la mezcla de tipos de datos en la misma máquina también puede cambiar el significado de los datos (por ejemplo, interpretar un bit en medio de un entero más largo como un bit de signo).
  • Endianness: si la biblioteca que está utilizando no maneja esto de manera consistente, es posible que deba manejarlo usted mismo. Por ejemplo, Java siempre usa el orden de bytes de red (big endian) para tipos de múltiples bytes. C y C ++ usan lo que decidiera el implementador de la biblioteca, típicamente el mismo que el procesador (little endian en Intel, big endian en la mayoría de los demás). Si este es un ejercicio rápido en un sistema, no es tan importante, pero sigue siendo un buen hábito prestar atención a esto y codificarlo si es necesario.

Los detalles específicos variarán según el marco, la plataforma y el idioma, pero esto debería cubrir los "errores" básicos con el archivo de E / S.

    
respondido por el user22815 27.08.2014 - 19:56
9

Además de todos los errores ya mencionados, si está creando un nuevo formato de archivo binario en lugar de leer y escribir datos en un formato existente, es absolutamente vital que incluya un encabezado de archivo : un bloque de datos al principio del archivo que identifica inequívocamente el formato del archivo y registra cualquier metadato que pueda ser necesario.

Los encabezados de archivos buenos incluyen al menos tres cosas:

  • Un " número mágico ", de al menos cuatro bytes. El número mágico DEBE rfc2119 sean los primeros N bytes en el archivo, DEBE nunca se han utilizado para cualquier otro formato de archivo que pueda desenterrar, y DEBE contener al menos un byte que no sea un carácter ASCII imprimible. Consulte la especificación de PNG para saber cómo diseñar un número mágico realmente completo . Consulte el código fuente del comando file(1) para obtener una base de datos de números mágicos existentes que sea tan completa como pueda encontrar. .

    El punto de un número mágico es etiquetar de forma inequívoca el archivo, dentro de la banda, con su formato. Si no incluye un número mágico, o no es lo primero en el archivo, corre el riesgo de que los programas identifiquen erróneamente su archivo como otro tipo de archivo otro , lo que lleva a la pérdida de datos. virus que escapan a la detección y otras catástrofes similares.

  • Una indicación de la versión del formato de archivo. Incluso si piensa que nunca tendrá que revisar su formato de archivo drásticamente, haga que los siguientes dos bytes después del número mágico sean 00 00 y documente que este es un número de versión de 16 bits en alguna endianidad definida (lo que quiera , pero elija uno y manténgalo en todo el archivo ) y se incrementará si el significado de los datos subsiguientes cambia radicalmente. Tu futuro yo te lo agradecerá.

    (La especificación PNG toma una ruta diferente aquí, especificando que los formatos de trozos están congelados, y que todos los cambios futuros en el formato tomarán la forma de nuevos tipos de trozos. Eso también es válido, pero recomiendo el número mágico simple + versión enfoque de número para principiantes en el procesamiento de datos binarios. Las personas que diseñaron PNG se basaron en décadas de experiencia colectiva con formatos de imagen.)

  • Algún tipo de mecanismo para incrustar metadatos arbitrarios en el archivo. Esto puede ser tan simple como tener los siguientes dos bytes con un desplazamiento de 16 bits desde el final del encabezado hasta el comienzo de los datos reales, con todo lo que debe interpretarse como una clave UTF-8 -value pairs a la RFC 822 (es decir, " Tag: value\n "; si sigue esta ruta, recomiendo no permitir el plegado de líneas largas). Nuevamente, PNG es considerablemente más inteligente.

respondido por el zwol 28.08.2014 - 02:42
2

Diferentes arquitecturas tienen diferentes representaciones para enteros. El principal riesgo aquí es guardar la representación en bytes de un número entero en la máquina A y luego intentar leerlo de nuevo e interpretar los contenidos como números enteros en la máquina B. Si las máquinas A y B tienen diferentes tamaños para los números enteros y / o diferente endianness , lo más probable es que cause un comportamiento indefinido (por ejemplo, en C) o una excepción.

Dado que esto es solo un ejemplo de programación y no un programa "real", no es realmente un problema. Si se tratara de un programa real, normalmente no es una buena idea hacer rodar su propio formato binario específico de la aplicación; hay mejores soluciones, como SQLite o formatos de serialización basados en cadenas como JSON, YAML, XML, etc. Para valores simples sería suficiente convertirlos en una cadena; para listas simples, puede guardar una cadena por línea y simplemente dividir la entrada en las nuevas líneas cuando la vuelva a leer.

    
respondido por el Doval 27.08.2014 - 19:50

Lea otras preguntas en las etiquetas