Есть ли правильный способ создать формат файла?

12

Я создаю собственный формат файла для приложения, написанного на C # .NET, для хранения сохраненной информации и, возможно, ресурсов линейного проекта. Есть ли стандарт, как это сделать каким-либо образом? Я просто собирал Serializeсвои объекты в двоичный файл и создавал заголовок, который говорил бы мне, как анализировать файл. Это плохой подход?

corylulu
источник
2
Я бы избежал BinaryFormatter.
CodesInChaos
3
Какой бы подход (из ответов) вы ни выбрали, всегда указывайте номер версии в формате! Ваш вопрос уже говорит о том, что он может измениться, и номер версии сэкономит вам много усилий, если вам потребуется совместимость с backwarsd.
Ян Догген
Не забудьте правильно документировать формат
Старынкевич

Ответы:

11

Наиболее простой способ - это, вероятно, сериализовать вашу структуру в XML с использованием XMLSerializerкласса. Возможно, вам не нужно будет создавать отдельный заголовок и структуру тела - но сериализуйте все активы в XML. Это позволяет вам легко просматривать / редактировать файловую структуру вне вашей собственной программы и легко управляется.

Однако, если ваша файловая структура действительно сложна и содержит много разных ресурсов разных типов, так что сериализация всей структуры в XML слишком обременительна, вы можете посмотреть на сериализацию каждого актива в отдельности и сборку их в один пакет с использованием Packagingбиблиотеки в C # , По сути, именно так создаются .docx, .xslx, .pptx и другие форматы офисных файлов.

PSWG
источник
Да, мой проект намного сложнее, чем просто это, но я также пытаюсь сделать его менее читаемым для пользователя, поскольку мы можем развернуть его в поле в лицензионном контексте. В настоящее время я использую protobuf-netдля сериализации моих данных, и это прекрасно работает. Но я должен отдельно сериализовать фрагменты, так что то, о чем вы говорите с библиотекой Packaging, звучит так, как мне нужно.
corylulu
7
Боже, не XML
Джеймс
2
@James да, у XML есть свои недостатки, конечно. Я предпочитаю упаковку и XML в большинстве случаев по тем же причинам: 1. Это уже существующая инфраструктура, поэтому требует небольших усилий. 2. Другие системы легко поддерживать, так как это общепринятый стандарт. 3. Человеку легко проверить полученный файл для проверки процесса сериализации.
PSWG
XML имеет свои преимущества, но это из-за тех преимуществ, которые мне не нравятся при использовании XML-сериализатора. Я считаю, что это требует, чтобы XML был в определенном формате. XML - это полуструктурированный формат, который позволяет формату моего файла со временем меняться и при этом быть обратно совместимым и даже совместимым. В прошлом я писал свой собственный синтаксический анализ XML, стараясь не делать никаких предположений относительно порядка или отсутствующих тегов, о которых я не знаю в будущем. Если вы можете загрузить весь XML-файл, XPATH, вероятно, будет работать очень хорошо. В противном случае вы уйдете с более сложным анализом потока
Alan
Я хотел бы предложить , глядя в JSON
Basile Starynkevitch
7

От кого-то, кому приходилось анализировать много форматов файлов, у меня есть мнения по этому поводу с другой точки зрения для большинства.

  • Сделайте магическое число очень уникальным, чтобы детекторы формата файлов других людей не идентифицировали его как ваше. Если вы используете двоичный файл, выделите 8 или 16 случайно сгенерированных байтов в начале двоичного формата для магического числа. Если вы используете XML, выделите правильное пространство имен в своем домене, чтобы оно не могло конфликтовать с другими людьми. Если вы используете JSON, Бог поможет вам. Может быть, кто-то уже решил решение этой мерзости формата.

  • План обратной совместимости. Сохраните номер версии формата так, чтобы более поздние версии вашего программного обеспечения могли иметь дело с различиями.

  • Если файл может быть большим или в нем есть разделы, которые по какой-то причине могут захотеть пропустить, убедитесь, что есть хороший способ сделать это. XML, JSON и большинство других текстовых форматов особенно страшны для этого, потому что они заставляют читателя анализировать все данные между начальным и конечным элементом, даже если им это не важно. EBML несколько лучше, потому что он хранит длину элементов, позволяя вам пропустить весь путь до конца. Если вы создаете пользовательский двоичный формат, существует довольно распространенный дизайн, в котором вы сохраняете идентификатор фрагмента и длину в качестве первого элемента в заголовке, а затем читатель может пропустить весь фрагмент.

  • Сохраните все строки в UTF-8.

  • Если вы заботитесь о долгосрочной расширяемости, сохраните все целые числа в форме переменной длины.

  • Контрольные суммы хороши тем, что позволяют читателю немедленно прервать неверные данные, вместо того, чтобы потенциально заходить в разделы файла, что может привести к неверным результатам.

Trejkaz
источник
+1 за то, что заставил меня понять, что я не единственный человек, который думает, что json - мерзость формата.
RubberDuck
Почему ненависть к JSON? Просто поместите известную строку в известное место, чтобы определить формат. Проблема решена.
Эсбен Сков Педерсен
Он не идеален, но он работает без проблем с javascript, быстрее анализирует, чем XML и имеет меньший размер, и, тем не менее, удобочитаем для человека.
corylulu
1
"Почему ненавижу JSON?" Отсутствие поддержки удобочитаемых комментариев, экранирования от дерьма Unicode и странного синтаксиса, требующего от меня заключать в кавычки ключи, даже если они никогда не содержат пробелов. Плюс обычная неспособность что-либо расширять, потому что никто не задумывался о пространстве имен ... к тому времени, когда вы решите это, вы получите нечто, что вначале будет выглядеть даже хуже, чем XML, и все за что, преимущество в том, чтобы избежать некоторого угла скобки?
Трейказ
Да, но, как и во всех вещах, связанных с программированием, используйте правильный инструмент для работы. Существуют приложения, в которых XML лучше, чем JSON, и наоборот.
corylulu
4

Ну, иногда то, что вы описываете, может быть очень плохим подходом. Это предполагает, что когда вы говорите «сериализация», вы говорите об использовании способности языка / фреймворка просто брать объект и выводить его напрямую в некоторый двоичный поток. Проблема в том, что классовые структуры меняются с годами. Сможете ли вы перезагрузить файл, созданный в предыдущей версии вашего приложения, если все ваши классы изменятся на более новый?

Для долгосрочной стабильности формата файла, я считаю, что лучше немного закатать рукава и специально написать свои собственные методы «сериализации» / «потоковой передачи» в ваших классах. т.е. вручную обрабатывать запись значений в поток. Напишите заголовок, который вы указали, который описывает версию формата, а затем данные, которые вы хотите сохранить, в том порядке, в котором вы хотите. Что касается чтения, обработка различных версий формата файла становится намного проще.

Другой вариант, конечно, XML или JSON. Не обязательно лучший для бинарного тяжелого контента, но простой и понятный человеку ... большой плюс для долгосрочной жизнеспособности.

GrandmasterB
источник
Я сериализуюсь с использованием protobuf-net ( code.google.com/p/protobuf-net ), который является расширяемым. Но ваши пункты верны, однако я не думаю, что это какой-либо метод форматирования файла, который защищен от этого.
corylulu
Да ... вот почему я говорю, что иногда нужно просто испачкать руки и обработать порядок, в котором данные записываются и загружаются вручную.
GrandmasterB
Приложение, которое я создаю, далеко не динамично и имеет слишком много значений для чего-то подобного.
corylulu
1
Чем сложнее приложение, тем важнее иметь очень точный контроль над форматом файла. Имейте в виду, я не говорю, что у каждого класса не должно быть своего собственного потока вывода ... просто, что вы должны контролировать это для каждого класса. Тогда просто вызовите эти процедуры.
GrandmasterB
Да, у меня есть методы, которые обновляют унаследованные версии до современных версий, и у меня есть очень четкая схема расположения моих классов. Я не слишком беспокоюсь об этом, но я согласен, что это важно. Я работаю над этим почти год, поэтому у меня есть довольно четкое представление о том, как работает эта структура.
corylulu
1

Я также хотел бы услышать ответы на этот вопрос от людей с большим опытом, чем я сам.

Я лично реализовал несколько форматов файлов для своей работы и перешел на использование формата файлов XML. Мои требования и аппаратное обеспечение, с которым я постоянно взаимодействую, меняются, и я не могу сказать, что мне нужно будет добавить в формат в будущем. Одним из основных преимуществ XML является то, что он полуструктурирован . По этой причине я обычно избегаю автоматической сериализации XML, предоставляемой .NET, потому что считаю, что она заставляет ожидать точный формат.

Моя цель состояла в том, чтобы создать формат XML, который позволял бы добавлять новые элементы и атрибуты в будущем и чтобы порядок тегов не имел значения, когда это возможно. Если вы уверены, что можете загрузить весь файл в память, XPATH , вероятно, является хорошим выбором.

Если вы имеете дело с особенно большими файлами или по другим причинам не можете загрузить файл сразу, тогда вам, вероятно, придется использовать XmlStreamReader и сканировать на наличие известных элементов, а затем возвращаться в эти элементы с помощью ReadSubtree и сканировать снова ...

Алан
источник
Этот ответ не очень направлен на вопрос, этот сайт не предназначен для обсуждения, а предназначен для не спекулятивных вопросов и ответов. В вашем ответе есть несколько обоснованных замечаний, которые можно использовать для аргументации предположения о том, почему подход спрашивающего является хорошим или плохим, но он не очень сфокусирован. Пожалуйста, сфокусируйте свой ответ на вопросе еще немного, спасибо!
Джимми Хоффа
@JimmyHoffa Хотя мой ответ также поддержал вопрос ОП, я дал понять, что предлагаю полуструктурированный подход XML ... но я понимаю, что вы имеете в виду, я могу отредактировать
Алан