Existe uma maneira adequada de criar um formato de arquivo?


12

Estou criando um formato de arquivo proprietário para um aplicativo que escrevi em C # .NET para armazenar informações salvas e, talvez, os ativos do projeto na linha. Existe um padrão sobre como fazer isso de alguma maneira? Eu estava simplesmente indo para Serializemeus objetos em binário e criando um cabeçalho que me diria como analisar o arquivo. Esta é uma abordagem ruim?


2
Eu evitaria BinaryFormatter.
CodesInChaos

3
Qualquer que seja a abordagem (das respostas) que você escolher, sempre inclua um número de versão no formato! Sua pergunta já sugere que isso pode mudar, e o número da versão poupará muito esforço se você precisar ser compatível com versões anteriores.
Jan Doggen

Não se esqueça de documentar corretamente o formato
Basile Starynkevitch

Respostas:


11

O método mais direto é provavelmente serializar sua estrutura para XML usando a XMLSerializerclasse Você provavelmente não precisaria criar um cabeçalho e uma estrutura de corpo separados - mas serialize todos os ativos em XML. Isso permite que você inspecione / edite facilmente sua estrutura de arquivos fora do seu próprio programa, e é facilmente gerenciável.

No entanto, se sua estrutura de arquivos for realmente complexa, contendo muitos ativos diferentes de tipos diferentes, como serializar toda a estrutura para XML é muito onerosa, você pode serializar cada ativo separadamente e compilá-los em um único pacote usando a Packagingbiblioteca em C # . É basicamente assim que são construídos os formatos .docx, .xslx, .pptx e outros arquivos de escritório.


Sim, meu projeto é muito mais complexo do que apenas isso, mas também estou tentando torná-lo menos legível para o usuário, pois podemos implantá-los em um campo em um contexto licenciado. Atualmente, estou usando protobuf-netpara serializar meus dados e isso funciona muito bem. Mas tenho que serializar peças separadamente, para que você esteja falando com a biblioteca de empacotamento parece o que eu preciso.
corylulu

7
Caro deus não XML
James

2
@ James, sim, o XML tem suas desvantagens, é claro. Eu sou a favor do empacotamento e do XML na maioria dos casos pelas mesmas razões: 1. é uma estrutura preexistente, portanto exige pouco esforço. 2. É fácil para outros sistemas suportar, pois é um padrão amplamente aceito. 3. É fácil para um humano inspecionar o arquivo resultante para verificar o processo de serialização.
PSWG

O XML tem vantagens, mas é por causa dessas vantagens que eu não gosto de usar o serializador de XML. Eu acredito que requer que o XML esteja em um formato específico. XML é um formato semiestruturado, que permite que meu formato de arquivo mude ao longo do tempo e ainda seja compatível com versões anteriores e posteriores. No passado, escrevi minha própria análise de XML, tendo o cuidado de não fazer suposições sobre pedidos ou de não haver tags de que não conheço no futuro. Se você puder carregar o arquivo XML inteiro, o XPATH provavelmente funcionará muito bem. Caso contrário, você ficará com uma análise de fluxo mais complicada #
Alan /

Eu sugeriria olhar JSON
Basile Starynkevitch

7

De alguém que teve que analisar muitos formatos de arquivo, tenho opiniões sobre isso de um ponto de vista diferente para a maioria.

  • Torne o número mágico muito exclusivo, para que os detectores de formato de arquivo de outras pessoas não o identifiquem como o seu. Se você usar binário, aloque 8 ou 16 bytes gerados aleatoriamente no início de um formato binário para o número mágico. Se você usa XML, aloque um espaço para nome adequado no seu domínio para que ele não possa entrar em conflito com outras pessoas. Se você usa JSON, Deus o ajude. Talvez alguém tenha resolvido uma solução para essa abominação de um formato até agora.

  • Planeje a compatibilidade com versões anteriores. Armazene o número da versão do formato de alguma forma, para que versões posteriores do seu software possam lidar com diferenças.

  • Se o arquivo puder ser grande ou houver seções que as pessoas possam ignorar por algum motivo, verifique se há uma boa maneira de fazer isso. XML, JSON e a maioria dos outros formatos de texto são particularmente terríveis para isso, porque forçam o leitor a analisar todos os dados entre o elemento inicial e final, mesmo que não se importem com isso. A EBML é um pouco melhor porque armazena o comprimento dos elementos, permitindo que você pule todo o caminho até o fim. Se você criar um formato binário personalizado, existe um design bastante comum em que você armazena um identificador de pedaço e um comprimento como a primeira coisa no cabeçalho e, em seguida, o leitor pode pular o pedaço inteiro.

  • Armazene todas as seqüências de caracteres em UTF-8.

  • Se você se preocupa com a extensibilidade a longo prazo, armazene todos os números inteiros em um formato de tamanho variável.

  • As somas de verificação são boas porque permitem que o leitor aborte imediatamente dados inválidos, em vez de entrar em seções do arquivo que possam produzir resultados confusos.


+1 por me fazer perceber que não sou a única pessoa que acha que json é uma abominação de um formato.
precisa

Por que o ódio por json? Basta colocar uma string conhecida em um local conhecido para identificar o formato. Problema resolvido.
Esben Skov Pedersen

Não é perfeito, mas funciona perfeitamente com javascript, mais rápido para analisar que XML e tamanho menor e ainda legível por humanos.
corylulu

1
"Por que o ódio por JSON?" Não há suporte para comentários legíveis por humanos, escape de Unicode porcaria e uma sintaxe estranha que exige que eu cite as chaves, mesmo que elas nunca contenham espaço em branco. Além da incapacidade usual de estender as coisas porque ninguém pensou em espaçamento de nomes ... quando você resolve esse problema, você acaba com algo que parece ainda pior do que o XML em primeiro lugar, tudo pelo que, o benefício de evitar algum ângulo suportes?
Trejkaz

Sim, mas como todas as coisas relacionadas à programação, use a ferramenta certa para o trabalho. Existem aplicativos em que o XML é melhor que o JSON e vice-versa.
Corlulu

4

Bem, há momentos em que você descreve pode ser uma abordagem muito ruim. Isso pressupõe que, quando você diz 'serializar', está falando sobre o uso da capacidade de uma linguagem / estrutura para simplesmente pegar um objeto e enviar diretamente para algum tipo de fluxo binário. O problema é que as estruturas de classes mudam ao longo dos anos. Você poderá recarregar um arquivo criado em uma versão anterior do seu aplicativo se todas as suas classes mudarem para uma mais nova?

Para estabilidade a longo prazo de um formato de arquivo, achei melhor arregaçar as mangas agora e escrever especificamente seus próprios métodos de 'serialização' / 'streaming' dentro de suas classes. ou seja, manipule manualmente a gravação de valores em um fluxo. Escreva um cabeçalho como você descreve, descrevendo a versão do formato e, em seguida, os dados que você deseja salvar na ordem em que deseja. No lado da leitura, manipular versões diferentes do formato do arquivo fica muito mais fácil.

A outra opção, é claro, é XML ou JSON. Não necessariamente o melhor para conteúdo pesado binário, mas simples e legível por humanos ... uma grande vantagem para a viabilidade a longo prazo.


Estou serializando usando o protobuf-net ( code.google.com/p/protobuf-net ), que é extensível. Mas seus pontos são válidos, no entanto, não acho que seja um método de formato de arquivo imune a isso.
27613 Corylulu

Sim ... é por isso que digo que às vezes você só precisa sujar as mãos e lidar com a ordem em que os dados são gravados e carregados manualmente.
GrandmasterB

O aplicativo que estou construindo é muito dinâmico e tem muitos valores para algo assim.
Corylulu

1
Quanto mais complicada a aplicação, mais importante é ter um controle muito fino sobre o formato do arquivo. Tenha em mente que não estou dizendo que cada classe não deve ter sua própria saída programável ... apenas que você deve controlar isso para cada classe. Em seguida, basta chamar essas rotinas.
GrandmasterB

Sim, eu tenho métodos para atualizar versões herdadas para versões modernas e tenho um layout muito claro de como minhas classes são organizadas. Não estou muito preocupado com isso, mas concordo que é importante. Estou trabalhando nisso há quase um ano, então tenho uma visão bastante clara de como a estrutura funciona.
Corylulu

1

Eu também adoraria ouvir respostas a esta pergunta de pessoas com anos de experiência mais do que eu.

Eu pessoalmente implementei vários formatos de arquivo para o meu trabalho e passei a usar um formato de arquivo XML. Meus requisitos e hardware com os quais interajo mudam o tempo todo e não há como dizer o que precisarei adicionar ao formato no futuro. Uma das principais vantagens do XML é que ele é semiestruturado . Por esse motivo, geralmente evito a serialização XML automática que o .NET fornece porque acredito que obriga a esperar um formato exato.

Meu objetivo era criar um formato XML que permitisse adicionar novos elementos e atributos no futuro e que a ordem das tags não importasse sempre que possível. Se você tem certeza de que pode carregar todo o arquivo na memória, o XPATH é provavelmente uma boa escolha.

Se você estiver lidando com arquivos particularmente grandes ou por outros motivos não puder carregar o arquivo de uma só vez, provavelmente ficará com o uso de um XmlStreamReader e a varredura de elementos conhecidos e a recursão nesses elementos com o ReadSubtree e a varredura novamente ...


Esta resposta não é muito direcionada ao Q. Este site não pretende ser um quadro de discussão, mas destina-se a perguntas e respostas não especulativas. Você tem alguns pontos válidos em sua resposta que podem ser usados ​​para argumentar uma sugestão de por que a abordagem do questionador é ou não boa, mas não é muito focada. Concentre sua resposta na pergunta um pouco mais, obrigado!
Jimmy Hoffa 13/03

@JimmyHoffa Enquanto a minha resposta também apoiou a pergunta do OP, eu deixar claro que eu estava sugerindo uma abordagem semi-estruturado XML .. mas eu vejo o que você quer dizer, eu pode editar
Alan
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.