Czy istnieje właściwy sposób utworzenia formatu pliku?

12

Tworzę zastrzeżony format pliku dla aplikacji napisanej w C # .NET do przechowywania informacji o zapisywaniu i być może w dół zasobów projektu. Czy istnieje standard, jak to zrobić w jakikolwiek sposób? Po prostu przechodziłem do Serializemoich obiektów w formacie binarnym i tworzyłem nagłówek, który powiedziałby mi, jak parsować plik. Czy to złe podejście?

Corylulu
źródło
2
Unikałbym BinaryFormatter.
CodesInChaos
3
Bez względu na to, jakie podejście wybierzesz (z odpowiedzi), zawsze dołącz numer wersji w formacie! Twoje pytanie już sugeruje, że może się zmienić, a numer wersji pozwoli ci zaoszczędzić wiele wysiłku, jeśli musisz być kompatybilny z backwarsd.
Jan Doggen
Nie zapomnij odpowiednio udokumentować formatu
Basile Starynkevitch

Odpowiedzi:

11

Najprostszą metodą jest prawdopodobnie serializacja struktury do XML przy użyciu XMLSerializerklasy. Prawdopodobnie nie trzeba tworzyć osobnego nagłówka i struktury treści - ale serializować wszystkie zasoby do formatu XML. Pozwala to na łatwą kontrolę / edycję struktury plików poza własnym programem i jest łatwy do zarządzania.

Jeśli jednak struktura plików jest naprawdę złożona i zawiera wiele różnych zasobów różnych typów, na przykład szeregowanie całej struktury do formatu XML jest zbyt uciążliwe, możesz rozważyć szeregowanie każdego zasobu osobno i skompilowanie ich w jednym pakiecie przy użyciu Packagingbiblioteki w języku C # . Zasadniczo tak powstają pliki .docx, .xslx, .pptx i inne formaty plików biurowych.

pswg
źródło
Tak, mój projekt jest o wiele bardziej złożony, ale staram się również, aby był mniej czytelny dla użytkownika, ponieważ możemy wdrożyć je w polu w kontekście licencji. Obecnie używam protobuf-netdo serializacji moich danych i tyle działa świetnie. Ale muszę oddzielnie serializować utwory, więc to, o czym mówisz z biblioteką opakowań, brzmi jak to, czego potrzebuję.
corylulu
7
Dobry Boże, nie XML
James
2
@James tak XML ma oczywiście swoje wady. W większości przypadków preferuję pakowanie i XML z tych samych powodów: 1. Jest to wcześniej istniejący framework, więc wymaga niewielkiego wysiłku. 2. Obsługa innych systemów jest łatwa, ponieważ jest to powszechnie akceptowany standard. 3. Człowiek może łatwo sprawdzić wynikowy plik, aby zweryfikować proces serializacji.
pswg
XML ma zalety, ale to z powodu tych zalet nie lubię używać serializatora XML. Uważam, że wymaga, aby XML był w określonym formacie. XML jest częściowo ustrukturyzowanym formatem, który pozwala mi zmieniać format mojego pliku w czasie i nadal być kompatybilny wstecz, a nawet dalej. W przeszłości pisałem własne parsowanie XML, uważając, aby nie przyjmować żadnych założeń dotyczących zamawiania lub nieobecności tagów, których nie znam w przyszłości. Jeśli możesz załadować cały plik XML, XPATH prawdopodobnie działałoby całkiem dobrze. W przeciwnym razie twoja lewica z bardziej skomplikowanym parsowaniem strumienia
Alan
Proponuję
zajrzeć
7

Od kogoś, kto musiał przeanalizować wiele formatów plików, mam na ten temat opinie z innego punktu widzenia niż większość.

  • Spraw, aby magiczna liczba była bardzo unikalna, aby ludzkie detektory formatu plików dla innych formatów nie identyfikowały jej jako twojej. Jeśli używasz pliku binarnego, przydziel 8 lub 16 losowo wygenerowanych bajtów na początku formatu binarnego dla liczby magicznej. Jeśli używasz XML, przydziel odpowiednią przestrzeń nazw w swojej domenie, aby nie mogła kolidować z innymi osobami. Jeśli używasz JSON, niech Bóg ci pomoże. Być może ktoś już wymyślił rozwiązanie tej obrzydliwości formatu.

  • Zaplanuj zgodność wsteczną. Przechowuj numer wersji tego formatu, aby późniejsze wersje oprogramowania radziły sobie z różnicami.

  • Jeśli plik może być duży lub istnieją jego sekcje, które ludzie mogą chcieć pominąć z jakiegoś powodu, upewnij się, że jest to dobry sposób na zrobienie tego. XML, JSON i większość innych formatów tekstowych są szczególnie straszne, ponieważ zmuszają czytelnika do parsowania wszystkich danych między elementem początkowym i końcowym, nawet jeśli ich to nie obchodzi. EBML jest nieco lepszy, ponieważ przechowuje długość elementów, umożliwiając przeskakiwanie do samego końca. Jeśli utworzysz niestandardowy format binarny, istnieje dość powszechny projekt, w którym jako pierwszy element w nagłówku zapisujesz identyfikator porcji i długość, a następnie czytnik może pominąć cały fragment.

  • Przechowuj wszystkie ciągi znaków w UTF-8.

  • Jeśli zależy Ci na długoterminowej rozszerzalności, przechowuj wszystkie liczby całkowite w postaci zmiennej długości.

  • Sumy kontrolne są fajne, ponieważ pozwalają czytelnikowi natychmiast przerwać nieprawidłowe dane, zamiast potencjalnie wchodzić w sekcje pliku, które mogą dawać mylące wyniki.

Trejkaz
źródło
+1 za uświadomienie mi, że nie jestem jedyną osobą, która uważa, że ​​Json jest obrzydliwością formatu.
RubberDuck
Dlaczego nienawidzisz Jsona? Wystarczy umieścić znany ciąg w znanym miejscu, aby zidentyfikować format. Problem rozwiązany.
Esben Skov Pedersen
Nie jest idealny, ale bezproblemowo współpracuje z javascript, szybciej parsuje niż XML i ma mniejszy rozmiar, i nadal jest czytelny dla człowieka.
corylulu,
1
„Dlaczego nienawiść do JSON?” Brak wsparcia dla czytelnych dla człowieka komentarzy, bzdurne unikanie Unicode i dziwna składnia wymagająca ode mnie cytowania kluczy, mimo że nigdy nie zawierają białych znaków. Plus zwykła niezdolność do rozszerzania rzeczy, ponieważ nikt nie pomyślał o przestrzeni nazw ... zanim to rozwiążesz, skończysz z czymś, co wygląda jeszcze gorzej niż XML w pierwszej kolejności - wszystko po to, z korzyścią unikania pewnego kąta wsporniki?
Trejkaz
Tak, ale jak w przypadku wszystkich rzeczy związanych z programowaniem, użyj odpowiedniego narzędzia do pracy. Istnieją aplikacje, w których XML jest lepszy niż JSON i odwrotnie.
corylulu,
4

Czasami to, co opisujesz, może być bardzo złym podejściem. Zakłada się to, gdy mówisz „serializuj”, że mówisz o użyciu umiejętności języka / frameworku, aby po prostu wziąć obiekt i wyprowadzić bezpośrednio do jakiegoś strumienia binarnego. Problemem jest zmiana struktur klasowych na przestrzeni lat. Czy będzie można ponownie załadować plik utworzony w poprzedniej wersji aplikacji, jeśli wszystkie klasy zmienią się w nowszej?

Aby uzyskać długoterminową stabilność formatu pliku, uważam, że lepiej jest teraz zakasać rękawy i napisać własne metody „serializacji” / „przesyłania strumieniowego” w swoich klasach. tzn. ręcznie obsłużyć zapisywanie wartości do strumienia. Napisz nagłówek, jak podajesz, opisujący wersję formatu, a następnie dane, które chcesz zapisać w kolejności, w jakiej chcesz. Po stronie odczytu obsługa różnych wersji formatu pliku jest znacznie łatwiejsza.

Inną opcją jest oczywiście XML lub JSON. Niekoniecznie najlepszy w przypadku ciężkich treści binarnych, ale prosty i czytelny dla człowieka ... duży plus za długoterminową rentowność.

Grandmaster B.
źródło
Serializuję za pomocą protokołu protobuf-net ( code.google.com/p/protobuf-net ), który jest rozszerzalny. Ale twoje punkty są ważne, jednak nie sądzę, że jest to jakakolwiek metoda formatu pliku, która jest na to odporna.
corylulu
Tak ... dlatego mówię, że czasami musisz tylko ubrudzić sobie ręce i obsłużyć kolejność, w której dane są zapisywane i ładowane ręcznie.
GrandmasterB
Aplikacja, którą tworzę, jest zbyt dynamiczna i ma o wiele za dużo wartości na coś takiego.
corylulu
1
Im bardziej skomplikowana aplikacja, tym ważniejsza jest bardzo dokładna kontrola formatu pliku. Pamiętaj, że nie mówię, że każda klasa nie powinna mieć własnego strumienia wyjściowego ... po prostu powinieneś kontrolować to dla każdej klasy. Następnie po prostu wywołaj te procedury.
GrandmasterB
Tak, mam metody, które aktualizują starsze wersje do współczesnych wersji i mam bardzo przejrzysty układ tego, jak są ułożone moje klasy. Nie martwię się tym zbytnio, ale zgadzam się, że to ważne. Pracuję nad tym od prawie roku, więc mam dość jasny obraz tego, jak działa jego struktura.
corylulu
1

Ja również uwielbiam usłyszeć odpowiedź na to pytanie od ludzi z lat więcej doświadczenia niż ja.

Osobiście zaimplementowałem kilka formatów plików do swojej pracy i przeszedłem do używania formatu pliku XML. Moje wymagania i sprzęt, z którym współpracuję, zmieniają się cały czas i nie wiadomo, co będę musiał dodać do formatu w przyszłości. Jedną z głównych zalet XML jest to, że jest częściowo ustrukturyzowany . Z tego powodu generalnie unikam automatycznej serializacji XML, którą zapewnia .NET, ponieważ uważam, że zmusza go do oczekiwania na dokładny format.

Moim celem było stworzenie formatu XML, który pozwalałby na dodawanie nowych elementów i atrybutów w przyszłości oraz aby kolejność znaczników nie miała znaczenia, o ile to możliwe. Jeśli masz pewność, że możesz załadować cały plik do pamięci, XPATH jest prawdopodobnie dobrym wyborem.

Jeśli masz do czynienia ze szczególnie dużymi plikami lub z innych powodów nie możesz załadować pliku naraz, prawdopodobnie prawdopodobnie pozostaje Ci użycie XmlStreamReader i skanowanie w poszukiwaniu znanych elementów i rekurencja w te elementy za pomocą ReadSubtree i ponowne skanowanie ...

Alan
źródło
Ta odpowiedź nie jest bardzo skierowana do Q, ta strona nie ma być forum dyskusyjnym, ale raczej jest przeznaczona do niespekulacyjnych pytań i odpowiedzi. W swojej odpowiedzi podałeś kilka ważnych argumentów, które mogłyby posłużyć do uzasadnienia sugestii, dlaczego podejście pytającego jest dobre lub złe, ale nie jest zbyt skoncentrowane. Skoncentruj swoją odpowiedź na pytaniu jeszcze bardziej, dzięki!
Jimmy Hoffa
@JimmyHoffa Chociaż moja odpowiedź poparła również pytanie PO, wyjaśniłem, że sugeruję częściowo ustrukturyzowane podejście XML .. ale rozumiem, co masz na myśli, mogę edytować
Alan