Consideraciones al diseñar un tipo de archivo

8

Estoy a punto de comenzar a escribir un proceso para guardar parte de la estructura de datos del código en un archivo de algún tipo propietario, aún no definido. Sin embargo, nunca antes había diseñado un tipo o estructura de archivo.

  • ¿Hay alguna cosa, en general, que debería considerar antes de comenzar mi diseño?
  • ¿Hay alguna buena práctica aceptada aquí? ¿Malas prácticas que debo evitar?
  • ¿Qué hacer y qué no hacer absoluto?
Andy Hunt
fuente
3
Hola desde 2016! Esta es la definición del libro de texto de una pregunta que es demasiado amplia :) Sería útil si proporcionara detalles sobre lo que está tratando de lograr. La mayoría de los formatos de archivo propietarios están diseñados para algo . ¿Cuáles son tus requisitos?
Andres F.
No olvide el beneficio clave de usar un formato estándar: otras herramientas y aplicaciones podrán ingerirlo más fácilmente. Y es posible que no sea la única persona que trabaja con esos datos. Si trabaja con ese principio en mente, su software será más flexible, y eso tiene una manera de simplificar las cosas.
Joey Adams

Respuestas:

20

Primero, trate de encontrar un formato lo suficientemente cercano a lo que está a punto de construir. En general, es mejor usar el formato de alguien que inventar el suyo, incluso si el formato parece ser un poco más complejo de lo que necesita 1 .

Si no puede encontrar un formato listo para usar adecuado, vea si puede crear uno propio sobre un formato de propósito general existente, como XML o XML binario . Esto debería ser posible en casi todos los casos cuando esté a punto de comenzar un nuevo formato de archivo. El XML basado en texto ocupa más espacio, pero le da a los humanos cierta capacidad de lectura. Sin embargo, si se encuentra utilizando la codificación Base-64 dentro de un archivo XML, es una clara indicación de que debería haber utilizado una codificación binaria.

En cuanto a las buenas y malas prácticas, asegúrese de no "incorporar" la función de hardware de su plataforma de destino inicial en el diseño de su formato de archivo. Específicamente, asegúrese de que sus números estén almacenados en un formato que pueda leerse correctamente en plataformas con una capacidad de escritura diferente a la del escritor, y que sus cadenas orientadas al usuario estén almacenadas en UNICODE.

Otra buena práctica es incluir un encabezado desde el cual es posible determinar el tipo de su archivo en caso de que su extensión no esté o sea incorrecta. Es una buena idea incluir una versión de su formato de archivo en el encabezado. Esto le permitiría cambiar el formato más adelante y seguir siendo compatible con versiones anteriores.

Si es posible, no haga que su formato dependa de los detalles del mecanismo de serialización predeterminado integrado en su plataforma. Por ejemplo, los objetos Java binarios serializados no tienen un buen formato de archivo 2 .

Finalmente, decida si sus archivos deben ser transferibles . Esto introduce una complejidad adicional, porque uno debería ser capaz de interpretar "fotogramas" individuales de su archivo de forma aislada. Sin embargo, en los casos en que necesita capacidad de transmisión, casi siempre debería poder localizar un formato de archivo adecuado que ya exista.


1 Por otro lado, debe evitar los formatos que requieren esfuerzos extraordinarios para soportar la complejidad que requiere su aplicación.

2 Sin embargo, esto no significa que no deba intentar integrar de forma personalizada la lectura y escritura de su nuevo formato con el esquema de serialización de su plataforma, solo que no debe confiar en los mecanismos predeterminados de serialización.

dasblinkenlight
fuente
3
Unicode no es un formato. Es solo un mapeo. UTF-8 es un formato y generalmente se considera el formato adecuado para cadenas de texto portátiles (a menos que esté manejando texto CJK, en cuyo caso creo que UTF-16LE es probablemente el siguiente formato más común para cadenas)
squarewav
12

Lo primero que debe considerar es si realmente necesita un nuevo formato o si puede obtenerlo utilizando un formato ya existente. Considere usar SQLite; Si puede adaptar sus necesidades al modelo RDBMS, esto podría ahorrarle muchos dolores de cabeza. Además, considere usar XML o JSON, esto le ahorrará tener que escribir su propio analizador.

Si tiene que crear su propio formato, la primera consideración es si desea un formato de texto o un formato binario. Hay ventajas para ambos. Un formato de texto es una gran victoria para la portabilidad y tiene la ventaja de ser más fácil de leer o editar para un humano. Un formato binario podría ser más eficiente, pero tiene muchos problemas de portabilidad. No sienta la tentación de leer bytes directamente en variables, lo lamentará si necesita portar el código a otra plataforma.

Dirk Holsopple
fuente
Recuerde también, al diseñar su propio formato, que DEBE tener en cuenta los archivos rotos y asegurarse de que no rompan su aplicación. Además, si usa XML, por amor a todo lo que es valioso para usted: USE UN PARSER XML. No importa cuál (su idioma puede proporcionar uno), pero NO PARSE XML USTED MISMO.
Michael Kohne
SQLite si necesita una base de datos con registros individuales que se puedan cambiar al instante. JSON si está bien leer todos los datos en la memoria, modificarlos en la memoria y luego volver a escribirlos en el archivo.
gnasher729
1
@MichaelKohne: Lo mismo para JSON. Yo estimaría que el 10% de las preguntas de iOS son sobre bloqueos cuando algunos JSON contienen un valor nulo donde esperan una cadena.
gnasher729
2

Su primera y más importante decisión es usar un formato binario o uno basado en texto. Binario es el camino a seguir cuando tiene que volcar grandes cantidades en datos que no son cadenas. Pero tiene desventajas significativas:

  • Los datos binarios no son legibles por humanos. Como tal, hace que la depuración y / o ajuste de datos que ya están en el disco sea mucho más difícil. Esta es una de las razones por las cuales la filosofía de UNIX abarca tan fuertemente los archivos basados ​​en texto.

  • Los formatos binarios no se prestan para una futura expansión. Si bien esto se puede hacer, los puntos para la capacidad de expansión deben integrarse en el formato desde el principio. Por lo general, estos son

    1. un número mágico / cadena que identifica el formato

    2. un número de versión de formato

    3. campos reservados en posiciones estratégicas, que deben inicializarse a cero

    Los primeros dos generalmente aparecen justo al comienzo del archivo, mientras que los campos reservados generalmente se encuentran dispersos en el archivo.


Ahora, si sigue la ruta basada en texto, aquí hay algunas cosas en las que pensar:

  • Cualquier formato basado en texto define un nuevo mini idioma. Sepa esto y úselo para su ventaja.

  • Intenta mantener las reglas de tu mini-idioma lo más simple posible. No hay lugar donde el principio KISS sea más importante que cuando se diseña un formato de archivo basado en texto.

  • Intenta que tus archivos se expliquen por sí mismos.

  • No imponga restricciones innecesarias, como dónde puede aparecer el espacio en blanco y cuánto.

  • Eche un vistazo a varios formatos de archivo diferentes desarrollados para UNIX. Esto puede darle algunas buenas ideas.

  • Si es posible, use o adapte / expanda / restrinja un formato de archivo existente. El formato json es un buen punto de partida bastante legible. (Al menos mucho mejor que XML, que es un dolor de leer para los humanos).

  • Si el tamaño del archivo es un problema, puede considerar usar un formato basado en texto de todos modos, pero páselo a través de uno de los compresores estándar como gzipo lzma. Los compresores estándar aman la entrada de esa manera.


Si va por la ruta binaria, aquí hay algunas cosas a tener en cuenta:

  • Debe tener un encabezado con un número / cadena mágico y un número de versión. Por lo general, esto va al principio del archivo, pero también puede ir al final del archivo. Algunos archivos incluso pueden tener dos encabezados diferentes en la parte delantera y trasera, lo que brinda dos vistas independientes de los datos que contiene.

  • Debe tener un índice y debe tratar de mantener sus partes juntas. Esto le permite al lector descubrir rápidamente qué hay dentro del archivo, sin tener que escanear todo. Si no lo haces, podrías terminar leyendo todo dos veces.

  • Si tiene bits del archivo a los que solo se puede acceder como una secuencia en lugar de a través de una estructura de índice, incluya al menos un campo de longitud para cada registro en la secuencia. Un índice o tales campos de longitud son requisitos para los lectores que no entienden todos los detalles de su formato y necesitan omitir partes de él como cuadros negros. (Gracias a Jules por este.)

  • Cada objeto de datos dentro del archivo debe contener al menos un campo reservado para una futura expansión. Esto no necesita ser grande, pero debe estar allí. Porque, si no es así, no hay lugar donde pueda reconocer las características futuras.

  • Debe tener en cuenta la resistencia. Por lo general, eso significa que usted decide una vez si sus archivos deben codificarse en orden de bytes big endian o little endian, y se adhiere a esa decisión: manejar la endianess como esta es una molestia, pero no es tan malo como tener que tener en cuenta dos versiones diferentes de endianess en el archivo.

  • Sea generoso en el ancho de los campos que proporcione. Especialmente, cuando necesite codificar desplazamientos dentro del archivo, use siempre 64 bits. Los diseñadores de formatos de archivo han causado muchos dolores de cabeza que fueron demasiado conservadores con la cantidad de bits que asignaron.

cmaster - restablecer monica
fuente
Agregaré otro para archivos binarios: si tiene una secuencia de registros de tipo variable (que es una estructura muy útil) NO asuma que ningún lector del archivo comprende todos los tipos. Utilice indicadores de longitud para que se puedan omitir registros desconocidos.
Jules
@Jules Tienes razón :-) Agregué eso como punto 3 para los archivos binarios.
cmaster - reinstalar a monica el
0

Realmente depende de lo que estés haciendo. Debe ser lo más simple posible y no más simple. Veo a muchas otras personas empujando XML. Desaconsejo firmemente el uso de XML. XML es un desorden sobre especificado. La primera pregunta sería si sus estructuras de datos tienen ramas. ¿Qué significan listas de listas o listas de mapas o algo así? Si no, entonces una secuencia simple de registros de texto podría ser buena. CSV tal vez.

Si necesita rendimiento o acceso aleatorio, binario es bueno. Defina una secuencia de registros donde cada registro contenga una secuencia de datos que tengan un tamaño específico como un entero pequeño endian de 4 bytes para algún número o un entero de 2 bytes que especifique el número de bytes para una cadena UTF-8. Haga que cada registro comience con un número entero que especifique el tamaño del registro para que se pueda escanear todo el archivo sin leer realmente el contenido de los registros. Esto también le permite codificar registros in situ (lo que significa que puede mapear el archivo, codificar el registro y luego actualizar el tamaño después para minimizar la copia innecesaria). Este es el tipo de cosas que no puedes hacer con XML.

squarewav
fuente