Загрузка пользовательского формата файла iOS с помощью NSData и NSCoding

Я ищу некоторые рекомендации от некоторых программистов iOS Cocoa о том, как можно реализовать механизм для загрузки и анализа пользовательского формата файла в объекты модели, которые я буду использовать в памяти. Я знаю, что должно быть много способов расколоть этот орех, но позвольте мне поделиться основной идеей текущего пути, который я исследовал, и где я застрял.

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

%n|sectionName

... и следующие n строк разделены вертикальной чертой уникальным для этого раздела способом. В некоторых разделах есть строка заголовка, разделенная вертикальной чертой, за которой следуют n строк данных (также разделенных вертикальной чертой), а в других разделах может быть просто n строк, разделенных вертикальной чертой. В начале файла есть несколько коротких разделов, а затем, наконец, будет один огромный раздел, описывающий узлы k-арного дерева: их отношения родитель-потомок и любые данные, связанные с каждым узлом. Все говорят, что размер этих файлов исчисляется десятками мегабайт, возможно, больше в будущем.

Наконец, последняя часть контекста заключается в том, что я довольно новичок в программировании для iOS.

Я начал с использования NSFileHandle для получения представления файла как экземпляра NSData. Это было довольно просто, и, изучив интерфейс NSData и попробовав, как действовать дальше, я заметил протокол NSCoding, который претендует на роль средства для архивирования и сериализации объектов в (и из) представлений.

Я подумал, что это звучит как то, что мне может понадобиться, поскольку я склонен думать о форматах файлов как о просто представлениях, в которые можно маршалировать объекты моей модели. Однако, покопавшись в «Руководстве по программированию архивов и сериализаций», я начал сомневаться в себе. API, похоже, не подходит для того, чего я пытаюсь достичь.

Я иду в тупик здесь? Должен ли я искать подкласс NSInputStream вместо этого, или я должен использовать какой-то другой подход, который мне не хватает?


person pohl    schedule 05.04.2011    source источник


Ответы (4)


NSCoding, вероятно, неправильный подход. Он предназначен для сериализации и десериализации типов Objective-C, а не для анализа пользовательского формата файла.

Вероятно, также нет необходимости создавать подкласс NSInputStream. Лучше всего здесь, вероятно, использовать библиотеку C stdio, в частности fgets для чтения строк. Если вы действительно хотите использовать NSInputStream или NSFileHandle, вы, безусловно, можете, вам просто нужно будет самостоятельно разобрать каждую строку из строки (что на самом деле не так уж сложно).

person Anomie    schedule 10.04.2011
comment
Спасибо, что напомнили мне, что в моем распоряжении есть простой C. Я думаю, что я был слишком сосредоточен на поиске подходящего класса(ов) Objective C для использования. Так совпало, что вчерашняя запись в блоге BJ Homer хорошо поработала. объяснения ситуации, когда действительно может потребоваться создать подкласс NSInputStream. Я согласен, что моя ситуация не подходит. Еще раз спасибо! - person pohl; 15.04.2011

Я рекомендую использовать Ragel для обработки интеллектуального анализа. Это должно быть намного проще, чем использование NSScanner, когда у вас есть базовые леса для настройки синтаксического анализатора и подачи в него байтов до завершения синтаксического анализа.

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

То, как вы хотите получить байты для ввода в Ragel, также зависит от вас. Вы можете использовать стандартные потоки ввода-вывода C, потоки Foundation или дескрипторы файлов Foundation. Все, о чем заботится Ragel, — это заполучить буфер символов, чтобы он мог запустить его через конечный автомат, в который было скомпилировано ваше описание.

NSCoder, скорее всего, доставит больше проблем, чем пользы для ваших целей. Ожидается, что он будет использоваться как способ сохранения и декодирования объекта Obj-C, при этом кодирование/декодирование будет зависеть от требований объекта («Хорошо, теперь дайте мне int, теперь коротко, как насчет объекта Obj-C… ").

person Jeremy W. Sherman    schedule 11.04.2011
comment
Спасибо за указание на Ragel. Я серьезно рассмотрю этот вариант. - person pohl; 15.04.2011

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

Во-первых, для синтаксического анализа нужно подумать, есть ли смысл вообще использовать Objective-C. Я мог бы подумать о написании небольшого вспомогательного сценария Perl, который очень подходит для анализа текстовых файлов и записи вывода в файл XML или, лучше, в файл plist. Затем этот файл может быть прочитан с вашим кодом Objective-C, и вы сможете работать с данными. Вы также можете записать данные в базу данных sqlite, которая также является подходящим форматом файла, поскольку существуют соединители данных для широкого круга доступных языков (C, Perl, Python и т. д.).

Во-вторых, если вы хотите проанализировать текстовый файл, стоит обратить внимание на класс NSLineScanner, который используется для анализа текстового файла.

Я не вижу никаких преимуществ при использовании NSInputStream, так как он возвращает только необработанные байты.

Редактировать

Эта предварительная обработка с использованием другого языка невозможна на устройствах iOS, насколько мне известно. Так что этот вариант возможен только на Mac.

person GorillaPatch    schedule 05.04.2011
comment
Спасибо за ответ. К сожалению, я не могу изменить формат путем предварительной обработки. Я, вероятно, не придется писать его обратно. Что касается того, что я собираюсь делать с данными: я собираюсь создавать экземпляры объектов или структур (моей собственной разработки) в памяти. После этого происходит навигация, отображение и визуализация. Я буду хранить древовидную структуру в памяти, хотя данные, связанные с каждым узлом, могут быть чем-то, что я могу загружать по запросу, когда узлы посещаются пользователем. - person pohl; 06.04.2011
comment
Что ж, предварительная обработка предназначена только для того, чтобы облегчить вашу жизнь и реализовать частный, простой в использовании формат данных. Вы также можете делать все в Objective-C, но для анализа текста Perl гораздо мощнее, и вы можете связать его со своим приложением, и никто никогда не узнает, что вы используете его внутри. - person GorillaPatch; 06.04.2011
comment
Есть ли интерпретатор Perl в iOS? Будут ли Perl-скрипты доступны для загрузки в магазин приложений? - person pohl; 06.04.2011
comment
Ах, ты меня понял. Конечно нет. Я недостаточно внимательно прочитал ваш вопрос. Итак, вам нужно разобрать свои строки на C, C++ или Objective-C. Извиняюсь. - person GorillaPatch; 06.04.2011

Существует несколько наборов с открытым исходным кодом, связанных с синтаксическим анализом, каждый из которых предназначен для разных целей. Что-то из этого может быть полезно для вас, но упоминание их в ответ на ваш вопрос может быть полезно, по крайней мере, для других.

person Gary W. Longsine    schedule 12.04.2011