¿Hay una manera adecuada de crear un formato de archivo?

12

Estoy creando un formato de archivo patentado para una aplicación que escribí en C # .NET para almacenar información guardada y tal vez los activos del proyecto. ¿Hay alguna norma sobre cómo hacer esto de alguna manera? Simplemente iba a Serializemis objetos en binario y creaba un encabezado que me diría cómo analizar el archivo. ¿Es este un mal enfoque?

corylulu
fuente
2
Yo evitaría BinaryFormatter.
CodesInChaos
3
Cualquiera sea el enfoque (de las respuestas) que elija, ¡siempre incluya un número de versión en el formato! Su pregunta ya sugiere que puede cambiar, y el número de versión le ahorrará mucho esfuerzo si tiene que ser compatible con versiones anteriores.
Jan Doggen
No se olvide de documentar correctamente el formato
Basile Starynkevitch

Respuestas:

11

El método más directo es probablemente serializar su estructura a XML utilizando la XMLSerializerclase. Probablemente no necesite crear una estructura de encabezado y cuerpo separada, sino serializar todos los activos en XML. Esto le permite inspeccionar / editar fácilmente su estructura de archivos fuera de su propio programa, y ​​es fácilmente manejable.

Sin embargo, si la estructura de su archivo es realmente compleja, contiene muchos activos diferentes de diferentes tipos, de modo que serializar toda la estructura a XML es demasiado oneroso, puede considerar serializar cada activo por separado y compilarlos en un solo paquete usando la Packagingbiblioteca en C # . Esto es esencialmente cómo se construyen .docx, .xslx, .pptx y otros formatos de archivos de Office.

pswg
fuente
Sí, mi proyecto es mucho más complejo que eso, pero también intento que sea menos legible para el usuario, ya que podríamos implementarlo en un campo en un contexto con licencia. Actualmente estoy usando protobuf-netpara serializar mis datos y eso funciona muy bien. Pero tengo que serializar las piezas por separado, así que lo que estás hablando con la biblioteca de Empaquetado suena como lo que necesito.
corylulu
77
Querido dios, no XML
James
2
@ James, sí, XML tiene sus desventajas, por supuesto. Estoy a favor del empaquetado y XML en la mayoría de los casos por las mismas razones: 1. es un marco preexistente, por lo que requiere poco esfuerzo. 2. Es fácil de soportar para otros sistemas, ya que es un estándar ampliamente aceptado. 3. Es fácil para un humano inspeccionar el archivo resultante para verificar el proceso de serialización.
pswg
XML tiene ventajas, pero es por esas ventajas que no me gusta usar el serializador XML. Creo que requiere que el XML esté en un formato específico. XML es un formato semiestructurado, que permite que el formato de mi archivo cambie con el tiempo y siga siendo compatible con versiones anteriores e incluso anteriores. En el pasado, escribí mi propio análisis XML mientras tenía cuidado de no hacer suposiciones sobre pedidos o si no hay etiquetas que desconozco en el futuro. Si puede cargar todo el archivo XML, XPATH probablemente funcionaría bastante bien. De lo contrario, te quedarás con un análisis de secuencias más complicado
Alan
Sugeriría buscar en JSON
Basile Starynkevitch
7

De alguien que ha tenido que analizar muchos formatos de archivo, tengo opiniones sobre esto desde un punto de vista diferente a la mayoría.

  • Haga que el número mágico sea único para que los detectores de formato de archivo de otras personas no lo identifiquen erróneamente como suyo. Si usa binario, asigne 8 o 16 bytes generados aleatoriamente al comienzo de un formato binario para el número mágico. Si usa XML, asigne un espacio de nombres adecuado en su dominio para que no pueda entrar en conflicto con otras personas. Si usas JSON, que Dios te ayude. Quizás alguien ya haya resuelto una solución para esa abominación de un formato.

  • Planifique la compatibilidad con versiones anteriores. Almacene el número de versión del formato de alguna manera para que las versiones posteriores de su software puedan lidiar con las diferencias.

  • Si el archivo puede ser grande, o hay secciones de él que la gente quiera omitir por alguna razón, asegúrese de que haya una buena manera de hacerlo. XML, JSON y la mayoría de los otros formatos de texto son particularmente terribles para esto, porque obligan al lector a analizar todos los datos entre el elemento inicial y final, incluso si no les importa. EBML es algo mejor porque almacena la longitud de los elementos, lo que le permite saltar hasta el final. Si crea un formato binario personalizado, existe un diseño bastante común en el que almacena un identificador de fragmento y una longitud como lo primero en el encabezado, y luego el lector puede omitir todo el fragmento.

  • Almacene todas las cadenas en UTF-8.

  • Si le importa la extensibilidad a largo plazo, almacene todos los enteros en forma de longitud variable.

  • Las sumas de verificación son buenas porque le permiten al lector abortar inmediatamente los datos no válidos, en lugar de entrar potencialmente en secciones del archivo que podrían producir resultados confusos.

Trejkaz
fuente
+1 por hacerme darme cuenta de que no soy la única persona que piensa que json es una abominación de un formato.
RubberDuck
¿Por qué el odio por Json? Simplemente coloque una cadena conocida en una ubicación conocida para identificar el formato. Problema resuelto.
Esben Skov Pedersen
No es perfecto, pero funciona a la perfección con javascript, más rápido de analizar que XML y de menor tamaño, y aún legible por humanos.
corylulu
1
"¿Por qué odio a JSON?" No hay soporte para comentarios legibles por humanos, escapes de Unicode y una sintaxis extraña que me obliga a citar las claves a pesar de que nunca contienen espacios en blanco. Además de la incapacidad habitual de extender las cosas porque nadie pensó en el espacio de nombres ... cuando resuelves ese problema, terminas con algo que se ve incluso peor que XML en primer lugar, todo por qué, el beneficio de evitar algún ángulo ¿soportes?
Trejkaz
Sí, pero como con todas las cosas con la programación, use la herramienta adecuada para el trabajo. Hay aplicaciones donde XML es mejor que JSON y viceversa.
corylulu
4

Bueno, hay veces que lo que describe puede ser un enfoque muy malo. Esto se supone cuando dices 'serializar' que estás hablando de usar la capacidad de un lenguaje / marco para simplemente tomar un objeto y enviarlo directamente a algún tipo de flujo binario. El problema es que las estructuras de clase cambian con los años. ¿Podrás volver a cargar un archivo creado en una versión anterior de tu aplicación si todas tus clases cambian en una nueva?

Para la estabilidad a largo plazo de un formato de archivo, ahora me parece mejor remangarse un poco y escribir específicamente sus propios métodos de 'serialización' / 'transmisión' dentro de sus clases. es decir, manejar manualmente la escritura de valores en una secuencia. Escriba un encabezado como indica que describe la versión del formato, y luego los datos que desea guardar en el orden en que lo desea. En el lado de la lectura, manejar diferentes versiones del formato de archivo se vuelve mucho más fácil.

La otra opción, por supuesto, es XML o JSON. No necesariamente el mejor para contenido pesado binario, pero simple y legible para humanos ... una gran ventaja para la viabilidad a largo plazo.

Gran maestro B
fuente
Estoy serializando usando protobuf-net ( code.google.com/p/protobuf-net ) que es extensible. Pero sus puntos son válidos, sin embargo, no creo que sea un método de formato de archivo que sea inmune a esto.
corylulu
Sí ... por eso digo que a veces solo tienes que ensuciarte las manos y manejar el orden en que los datos se escriben y cargan manualmente.
GrandmasterB
La aplicación que estoy construyendo es muy dinámica y tiene demasiados valores para algo así.
corylulu
1
Cuanto más complicada es la aplicación, más importante es tener un control muy fino sobre el formato del archivo. Tenga en cuenta que no estoy diciendo que cada clase no debería tener su propia salida de transmisión ... solo que debe controlar eso para cada clase. Entonces solo llama a esas rutinas.
GrandmasterB
Sí, tengo métodos implementados que actualizan las versiones heredadas a versiones modernas y tengo un diseño muy claro de cómo se distribuyen mis clases. No estoy demasiado preocupado por eso, pero estoy de acuerdo en que es importante. He estado trabajando en esto durante casi un año, así que tengo una visión bastante clara de cómo funciona su estructura.
corylulu
1

También me encantaría escuchar las respuestas a esta pregunta de personas con años de experiencia más que yo.

Personalmente, he implementado varios formatos de archivo para mi trabajo, y he pasado a usar un formato de archivo XML. Mis requisitos y el hardware con el que interactúo cambian todo el tiempo, y no se sabe qué necesitaré agregar al formato en el futuro. Una de las principales ventajas de XML es que está semiestructurada . Por esta razón, generalmente evito la serialización XML automática que proporciona .NET porque creo que lo obliga a esperar un formato exacto.

Mi objetivo era crear un formato XML que permitiera agregar nuevos elementos y atributos en el futuro y que el orden de las etiquetas no importara siempre que fuera posible. Si está seguro de que puede cargar todo su archivo en la memoria, entonces XPATH es probablemente una buena opción.

Si está tratando con archivos particularmente grandes, o por otras razones no puede cargar el archivo de una sola vez, entonces probablemente se quede con un XmlStreamReader y escanee en busca de elementos conocidos y recurra a esos elementos con ReadSubtree y escanee nuevamente ...

Alan
fuente
Esta respuesta no está muy dirigida a la Q, este sitio no pretende ser un panel de discusión, sino que está destinado a preguntas y respuestas no especulativas. Tiene algunos puntos válidos en su respuesta que podrían usarse para argumentar una sugerencia de por qué el enfoque del interrogador es o no bueno, pero no está muy enfocado. Por favor, centre su respuesta en la pregunta un poco más, ¡gracias!
Jimmy Hoffa
@JimmyHoffa Si bien mi respuesta también apoyó la pregunta del OP, dejé en claro que estaba sugiriendo un enfoque semiestructurado de XML ... pero entiendo lo que quieres decir, puedo editarlo
Alan