20:28

Пушист. Чешите.
Здравствуйте!
Возникло у меня внезапно желание поизучать конвертеры и попробовать написать пару простеньких. Да вот хотя бы doc->txt, или, там, еще что-нибудь. Подскажите, что я должна для этого знать/почитать? Есть ли какой-то общий принцип написания конвертеров? До этого я никогда этим не занималась.

@темы: Вопрос

Комментарии
14.04.2016 в 21:00

Могут пригодиться знания (в зависимости от форматов и ОС, или многие, или некоторые):

Работа с текстом:
- работы со строками и массивами символов
- кодировки (Windows-1251, UTF-8, Unicode, а так же типы для хранения символов (в случае Си, С++): однобайтовые char, многобайтовые - wchar_t) (хотя бы поискать статью Джоэля Спольски о кодировках)

Алгоритмы и структуры данных:
- Конечные автоматы (Finity State Machine)
- Регулярные выражения (книга Фридла)
- структуры (struct), стеки

Дополнительно:
-Общие принципы и работа со сторонними библиотеками, реализующими алгоритм ZIP (Форматы .docx, .odt зазипованы, например.)
- основы XML и то, как с этим работать в вашем языке программирования.

П.С.
Старые вордовские форматы - не самое простое для новичка. Скорее предложил бы что-то в духе txt -> fb2, txt->html ...
14.04.2016 в 21:35

Пушист. Чешите.
Скорее предложил бы что-то в духе txt -> fb2
Приму ваш совет :)
Не могли бы вы примерно описать алгоритм? Или подсказать, с чего начать? Гугл вот мне сказал, например, что fb2 - xml файл. То есть, для того, чтобы конвертировать txt в fb2, например, мне нужно создать пустой fb2файл, посимвольно считывать txt, писать в fb2? Мне кажется, что процесс как-то не так проходит, но пока ничего не приходит в голову.
А зачем могут пригодиться знания конечных автоматов?
Большое вам спасибо за ответ!
14.04.2016 в 22:39

Med-ved, Для начала вопрос, какой язык используется? У каждого ЯП свои плюсы и свои минусы, когда речь о работе с текстом.

И стоит задуматься, что вы хотите получить/готовы сделать. Т.е. ответить на вопросы (на примере FB2: Буду ли создавать заголовки? Сколько заголовков может быть в выходном файле? Могут ли быть не только главы, но ещё и более крупное - "Части", "Разделы"? Где могут встретиться пробелы, переводы строки и как на это реагировать, что "писать в выход в этот момент?.).

По символьно считывать можно, но о таком слышать не доводилось. Обычно считывают по словам и отдельным знакам препинания (формально: токенам), или иногда можно по-строкам. (Разбивают на токены часто или примитивным способом (ищут индекс следующего пробела и берут подстроку (от одного пробела до другого, или до знака препинания), или с помощью движка регулярных выражений. Регулярки так же могут помочь определить особенности слова (проверка, начинается ли слово с заглавной буквы и не содержит ли только 4 буквы, например).

Потом эта последовательность токенов уже обрабатывается (часть сохраняясь в какие-то промежуточные стеки, массивы, структуры). В выходной файл, если входной не слишком большой (текст должен поместиться в оперативной памяти), можно сохранять уже на самом последнем этапе. (Хотя в некоторых случаях возможен и ваш вариант, но тогда, когда результат так же текстовый файл (FB2 и XML, очевидно не вполне текстовые файлы, хотя и выглядят таковыми, и даже могут создаваться по вашему принципу - "на лету".). ) )

Токен может хранить ещё и дополнительную информацию. Грубый пример на Си:
enum TokenType {WORD, POINT, WHITESPACE, EndOFString}; - Тип покена: слово, знак препинания (не важно какой именно), пробел, или ещё что.

struct Token {
char token[25]; - Текст токена
size_t len; - Длина токена.
TokenType type; - тип, чтобы можно было легко проверить при обработке в КА
size_t line_number; - Номер строки, в которой встретился
size_t pos_in_string; - его порядковый номер (или смещение от начала строки) в строке.
};
Ненужные поля могут быть опущены. Структуры даны примерно для иллюстрации, и не к чему не призывают.

Сделать из набора токенов нужную структуру (в памяти программы) уже могут помочь Конечные автоматы (КА) (в сложном ли виде через ООП, или как простой набросок на базе switch-case и enum-а) могут помочь обработке и организации. Например с помощью КА можно собрать токены, принадлежащие заголовку текста друг к другу, а текст - к тексту. (По сути это всё - примитивный вариант парсера для текста *можно погуглить*). (Это возможно не лучший подход, но я собирал токены в стек, и лишь когда фрагмент текста заканчивался (получал точку, например), превращал в строку, в уже нужном формате).
А ещё через КА можно задать последовательность в определённом порядке (НАЧАЛО ДОКУМЕНТА - ЖДУ ЗАГОЛОВОК - ЖДУ И СОХРАНЯЮ ТЕКСТ СТАТЬИ/ГЛАВЫ - ЖДУ ЗАГОЛОВОК ИЛИ ТЕКСТ...).


Если не писать в файл "на лету", то хранить тоже в чём-то вроде структур (можно уже не токенами, а собранными строками:
typedef struct {
char Title[256];
char *p[1024]; // Paragraph tag
size_t number_of_p;
} Chapter;

struct Book {
char Author;
Chapter [45];
};

*Совет: при работе с Юникодом нужно использовать в Си/С++ типы wchar_t, wstring. При считывании посимвольно может пригодиться тип unsigned char.*

Если выходной файл представляет собой XML документ, то по возможности лучше использовать библиотеку для работы с XML. Примитивным способом (представлять теги как набор символов тоже можно, но это не самый грамотный путь).
14.04.2016 в 22:57

На тему КА, если до этого особенно не встречалось, предлагаю посмотреть (Примеры на Си, но во первых это можно сказать "всеобщий язык", а во вторых - легко переписываемо на другой):
https://ru.wikipedia.org/wiki/Автоматное_программирование
http://chipenable.ru/index.php/programming-avr/item/90-realizatsiya-konechnogo-avtomata-state-machine.html
https://habrahabr.ru/post/241941/
http://www.devexp.ru/2011/02/konechnye-avtomaty-v-c/
14.04.2016 в 23:20

Пушист. Чешите.
Огромное вам спасибо за развернутый ответ!
Для начала вопрос, какой язык используется?
Я предпочитаю Java, но на С/С++ тоже могу (правда, костыльно)
Ваш подход поняла, действительно токены - добро :) И ссылки просмотрю, огромное за них спасибо : )
Я отниму еще вашего времени: а что делать, если, например, я хочу конвертировать какой-нибудь файл в графический формат? Png, например? Возможно ли это?
14.04.2016 в 23:32

Med-ved, Я предпочитаю Java
И она может дать всё, что нужно).

Я отниму еще вашего времени: а что делать, если, например, я хочу конвертировать какой-нибудь файл в графический формат? Png, например? Возможно ли это?
Графический, например JPG в Png возможно, но уже другими методами). (Берётся две библиотеки для работы с форматами (или одну, если она поддерживает несколько форматов), и выход одной направляется (используется как аргумент при вызове конструктора) другой. *Детали могут разниться, но принцип...)

Если же текст в Png, то тоже конечно возможно. Но там уже библиотека работы с изображениями должна уметь писать текст на картинку, и придётся рассчитывать его длину и высоту, чтобы не наложить строки и символы друг на друга. (Т.е. буквально: "Начать рисовать букву "А" в точке с координатами Х и У." Альтернатива: С/С++ + WinAPI (и вероятно GDI, или более современный аналог), с последующим сохранением результата в BMP и конвертацией в другой формат опять-таки библиотекой (или руками в Паинте).
14.04.2016 в 23:39

Пушист. Чешите.
Спасибо, в голове прояснилось : )
24.04.2016 в 14:15

Интересный инструмент для разбора формата и структуризации данных: habrahabr.ru/post/281595/