Pull to refresh

Comments 69

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


Во-первых, таких инструкций и так навалом, во-вторых, у читателя может быть IDEA, или вообще текстовый редактор. Не то чтобы это вообще никому не нужно, но как по мне — стоило бы ограничиться только особенностями проекта, которые нужно именно тут, и не рассказывать, как в эклипсе создать новый класс. При этом некоторые интересные вещи типа выбора версии JDK, или выбора версии зависимостей, которые нужны проекту — они остались практически за кадром.


Ну и так, для справки — большинство реальных книг в FB2 — это xml в zip. Так что для полноты картины следовало бы дописать распаковку.

Спасибо за советы! Учту на будущее. Однако, мне пока не попадались fb2 в zip, поэтому распаковку не делала. Поищу еще, если таких fb2 действительно много, добавлю.

Не за что. Кстати,


javafx-web
17

почему тут 17 версия, а остальные зависимости из этой же группы — 16? Ну то есть, я к тому же — можно поменьше уделить внимания картинкам, и побольше тому, что за зависимости вы притащили в проект, для чего они нужны, какие версии (соответствуют ли они друг другу и скажем версии JDK), ну и так далее. В конце концов, если у вас мавен проект, то для его сборки должно быть достаточно pom и возможно settings.xml (если зависимости вдруг не в централ репозитории).

Так получилось, потому что этот код - часть моего более крупного проекта. Из-за несовместимости других зависимостей (которых здесь нет), он не компилировался с версией 17 и выше. Пришлось менять на 16. Javafx-web просто пропустила, похоже. Но тем не менее, все работает.

Ну вот как по мне — эта часть по выбору зависимостей — она обычно самая интересная. А ее-то и нет )


Да, вопрос что не удалось найти готового — меня тоже смущает. Читалок FB2 на андроиде множество, что никто не опубликовал код для такой обычной задачи — верится сильно с трудом.

А вообще зачем искать сторонние библиотеки, если читалку fb2 можно написать самостоятельно за довольно короткое время? Об этом, в том числе, моя статья)

Ну, а как бы вы это оценили заранее, что оно получится быстро?

Заранее бы не оценила. Но поскольку выбрала второй вариант, значит, для меня так оказалось проще. Этот код я писала для себя, своих нужд, не для статьи и не для того, чтобы произвести на кого-то впечатление. Выбрала для себя кратчайший путь. Я действительно потратила время на поиски других вариантов. Но то, что выше предлагали, не попадалось. А нейронка предложила код с библиотекой, которая подходит для EPUB. К тому же, если нужна читалка попроще, возможно, сделать своими силами тоже вариант. Например, когда я подключила библиотеку для читалки файлов doc, моя программа "потяжелела" на 200 Мб. А до этого весила в 4 раза меньше. Читала где-то, что подключение стронних библиотек имеет и другие минусы. Поддержка, совместимость, производительность, ошибки в чужом коде и т.д.

Судя по Вики https://ru.wikipedia.org/wiki/FictionBook , в зипы упаковывается только формат FictionBook 3. Но с ним изначально что-то пошло не так. Повторюсь, мне такие FictionBook пока не попадались. Однако я учту вашу поправку, и в дальнейшем внесу изменения в свой проект.

Иная картина с форматом EPUB. Они-то как раз все упакованы в zip. Я его тоже разбирала, делала распаковку, и, возможно, выложу статью про EPUB.

Возможно, речь о том, что скачивается обычно .fb2.zip, а большинство современных читалок могут работать прямо с такими файлами, отображая их сразу как книги.

Ах, вот что имеется в виду! Я поняла. В таком случае идея с распаковщиком стоящая.

в zip обычно упаковывают, чтобы по инету/почте раздать проще было, так как fb2 по сути своей это XML, то его могут блокировать как "потенциально вредное содержимое".
Ещё с целью уменьшения размера файла, если основная масса это текст. Но выигрыша тут со спичечную головку.

Сам FB2 является XML, разумеется, но распространяется обычно зипованным, так компактнее и удобнее.
А готовые просмотрщики имеют обычно дополнительные плюшки, которые самому сделать можно, но требует времени. В качестве обучения — прекрасно подходит, но в целом всё необходимое делать самому невозможно.

У меня конечно задачи не было писать парсер fb2, была конвертация doc в mongodb

Но первая же ссылка при поиске с телефона
https://github.com/KursX/fb2parser

Уверен это все уже было сделано до вас, думаю есть решение и лучше

Поэтому мой вопрос, судя по вашему первому абзацу
Как вы искали?

Тем более там исходники и вы можете взять их отдельно пакетом в ваш проект

Спасибо за подсказку! Искала, но не нашла. У меня код попроще. Мне этого достаточно. Не исключаю, кому-то будет интересно решение по вашей ссылке. Я же предложила свой вариант.

Кстати, я поняла, почему мне не попался этот парсер. Он для Gradle, а я искала для Maven. Но я его поизучаю, когда буду делать версию для Андроид (если, конечно, решусь).

Помимо maven, я еще искала такие решения, которые работают с javafx. Так как у меня весь проект на javafx (для десктопа). А читалка - это только часть проекта (об этом я пишу подробнее ниже в комментариях). Целиком запрос выглядел примерно так: java fb2 maven javafx. Возможно, поэтому и не встретила ваш вариант. Насколько я поняла, он больше на Андроид рассчитан. К тому же, он написан 6 лет назад, и нужно проверять, будет ли работать с новыми версиями jre, javafx и другими зависимостями, которые использую в проекте.

Дам вам один совет, делайте проект сразу на Spring, UI на Angular. Все это можете упаковать например в Electron или в докер и запускать как свой сервис.
Зачем? Для обучения и разбора современных технологий.
Сделайте свой дизайн, каталог книг, и тд...

Пожалуйста, не надо привносить сложность там, где это не нужно. Вы написали маленькую читалку для fb2 и это прекрасно. Не надо усложнять ваше решение просто потому, что хайп и сейчас так модно.

Причем тут мода? Дело в спросе на работу и изучении технологий. JavaFx это старая малокому нужная. Совет был дан автору как сделать лучше для своей карьеры.

Спасибо за совет! В любом случае, я люблю учиться всему новому, и до новых технологий доберусь)

делайте проект сразу на Spring, UI на Angular. Все это можете упаковать например в Electron или в докер и запускать как свой сервис.

У java-разработчика попросили прикурить, он пошел строить спичечную фабрику...

Не все джависты одинаковы. Я бы не стал заворачивать бекенд, фронтенд в электрон только потому что лень изучать JavaFX )

А я как-то видел коммерческий софт — приложенька на 400+ метров, внутри неё фронт на html/jquery с электроном и бэк на php с апачем. Ладно хоть mysql туда не запихали.

Как программист осуждаю ) Но с точки зрения бизнеса, это оправданное решение, если это самый быстрый time to market.

Эта тема отлично раскрыта в книге Lean Startup, если вкратце, у Вас шанс на успех выше если Вы выпустите кривое, косое, кое как работающее решение НО раньше, чем позже но красивое и стабильно работающее.

Пользователи примут неидеальный продукт если он им нужен, а у Вас как предпринимателя появиться фидбек о том какой именно продукт им нужен. Это конкурентное преимущество.

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

Когда я последний раз это трогал — была, емнип, уже 7 мажорная версия (они выпускают новую примерно раз в год). Сейчас они продают уже 10-ю. И что-то мне подсказывает, что в архитектурном плане там ничего не изменилось.
Бизнесу важно чтобы покупатели покупали. Переделывать чтобы было по феншую и потребляло меньше ресурсов он просто так не будет.

Вы будете смеяться, но первую версию своего каталога электронных книг я сделала на html+css (с использованием фреймворка bootsprap). Делала чисто для себя и где-то полгода пользовалась. Потом поняла, что это извращение и решила изучить Java. А почему бы и нет?)

html+css (с использованием фреймворка bootsprap)

А чего тут такого :) Штука полезная, как минимум опыта набрали.

А ещё лучше взять KMM, jetpack compose и тогда у вас будет проект под Андроид, IOS и desktop безо всяких электронов

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

Похоже, но у меня попроще намного. Для нас лучше, конечно, чтобы данные подтягивались не с Амазона, а с Литреса и Лабиринта. Но у меня пока такого нет. Ручками забиваю обложку, содержание, описание. Но идея хорошая, сделать так, чтобы все это руками не надо было вносить. Будет, над чем поработать)

Учебный пример хороший, но на практике совершенно нерабочий.

Во-первых, при работе с любым основанным на XML форматом неплохо бы ориентироваться на его схему. Для FB2 её можно найти тут: https://github.com/gribuser/fb2/blob/master/FictionBook.xsd

Во-вторых, как тут уже писали, в 99% случаев файл будет не .fb2, а .fb2.zip или .fbz, то есть упакован в архив. Все читалки знают, что с таким файлом делать, и не стоит этим пренебрегать.

В-третьих, в FB2 часто больше одного блока <body>. Это связано с существованием в книгах сносок (лежат в <body name="notes">), которые надо, по-хорошему, корректно отображать. Сейчас пользователь вашей программы их вообще не увидит. Другие элементы тоже не учтены, но там всё ограничится сломавшимся форматированием.

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

PS Категорически не рекомендую парсить XML так, как это делаете вы. Воспользуйтесь специализированными классами, работа с XML как со строкой не доведёт до добра. Подробнее можно посмотреть, например, здесь: https://habr.com/ru/articles/339716/

Спасибо за отзыв и информацию о парсинге XML. Поизучаю. А вот по поводу блока body, я знаю, что их может быть более одного. Мой код это учитывает, так как он захватывает все содержимое между первым (indexOf) и самым последним (lastIndexOf) элементами body. Что касается всяких опций, вроде сносок, колонтитулов, настроек шрифтов, закладок и т.д., тут вы абсолютно правы. Будем над этим работать)

А вот по поводу блока body, я знаю, что их может быть более одного. Мой код это учитывает.

Попробуйте обработать файл, у которого блоки <body> идут не подряд, а чередуются с блоками <binary>. Стандарт это допускает. Кусочек кода

// Получение текста между тегами body      
int startBody = content.indexOf("<body>");
int endBody = content.lastIndexOf("</body>");

в этом случае включит в текст всё содержимое блоков <binary>, что явно некорректно. А если блок со сносками будет идти до основного блока текста, то его ваша программа просто пропустит, потому что начинается он не со строки "<body>", а со строки "<body name=\"notes\">".

Это возможно, но мне таких книг не попадалось. Но я подумаю, как избежать такого варианта. Спасибо.

Парсить xml регулярками - это чисто для изучения нормальная тема, для чего-то более-менее реально использующегося, лучше так не делать, в 99% случаев (1% - на какие-то редкие случаи вроде быстрого парсинга каких-то очень простых обрывков xml). Парсинг xml штука совсем не тривиальная с массой подводных камней, если ваша задача вытащить что-то из такого файла, а не потренироваться в самом парсинге, то лучше использовать стандартные парсеры, они возьмут на себя большую часть работы и решат массу проблем.

Убедили) Читалку FB2 переделаю для своего проекта. В читалке EPUB я уже воспользовалась библиотекой Jsoup для парсинга XML. Там почти все то же самое. Распаковка ZIP, потом парсинг XML. Но немного структура сложнее, и 2 версии (v2 и v3) с разными структурами XML. В них элементы раскиданы хаотично, о чем многие тут предупреждают, что такое возможно.Поэтому там без грамотного парсинга никак не обойтись. Если будет интерес у кого-нибудь, напишу статью про EPUB)

jsoup это всё таки про парсинг HTML, благо EPUB - это обычно XHTML/HTML.

да, вы правы. Основной контент в html. Но есть парочка xml, в одном из которых указывается порядок следования файлов html (это файл с расширением OPF), а в другом содержится навигация (файл с расширением NCX для v2). С другой стороны, jsoup действительно не очень хорошо парсит xml, с этим я тоже уже сталкивалась, разбирая docx. Рассматриваю другие варианты (по ссылке, которой поделились чуть выше в комментариях).

PS Категорически не рекомендую парсить XML так, как это делаете вы.
Воспользуйтесь специализированными классами, работа с XML как со строкой
не доведёт до добра.

"Но есть один нюанс" (c) - некоторый FB2 бывают некорректными. То есть не только не отвечают схеме FB2, а некорректные как XML вообще.
Из примерно пол-терабайта библиотеки нескажукакой таких до 1%, но это ломает все хатки.
DOM-парсеры ломаются на таких файлах все и сразу, SAX - не сразу, но тоже все.
Так что для противодействия падучести требуются специальные телодвижения. Ручная работа с XML - вполне себе вариант (хоть и не очень хороший, да).

ИМХО такие книги и обрабатывать нет смысла. Невалидная - нахрен с пляжа!

Продолжайте в том же духе, и, если не остановитесь, то, перечитав эту статью лет через 10, вы найдете в ней достаточно моментов, которые вам захочется сделать по-другому. Искренне желаю успеха на этом тернистом пути. А пока просто акцентирую внимание на моменте, который мне показался самым спорным в вашем решении - вы исходите из предположения, что между первым тэгом <description> и последним тэгом </description> всегда будет, условно говоря, "чистый текст с описанием" (то же относится к вашей обработке тэгов <body> и </body>). В частных случаях это может быть так, но обычно в xml-подобных форматах допускается произвольная вложенность тэгов, и на ней наивный алгоритм сразу даст сбой.

Спасибо на добром слове! Насчет description. Не исключено, что так и будет. Будем решать проблемы по мере поступления)

Я работаю на C#, а не на Java, поэтому расскажу, как бы я эту задачу решал на C#.

Сначала нужно раздобыть XSD-файл, описывающий схему fb2. Например, здесь: https://github.com/gribuser/fb2

Затем нужно на основе XSD сгенерировать C#-классы для всех типов, описанных в XSD-файле. Это можно сделать при помощи утилиты xsd.exe, которая входит в состав Microsoft SDK.

После этого сгенерированный код включается в состав проекта. Теперь, чтобы прочитать XML-файл и сконвертировать его в объект, нужно всего несколько строк кода на C#.

После этого уже можно работать в программе со сформированным объектом.

Подозреваю, что подобный инструментарий существует и для Java. При этом для чтения и преобразования fb2-файла вместо десятков строк кода (как в статье) понадобится от силы 5-10 строк кода.

Конечно, перед конвертацией XML-файла в объект файл необходимо валидировать, то есть проверить, действительно ли его формат соответствует XSD-схеме. Это тоже можно сделать путем написания нескольких строк кода на C#.

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

В моем случае использовалась часть стандарта, описывающая объекты недвижимости (кадастровые объекты). XSD-схема содержала несколько сотен элементов, а описание стандарта занимало более 600 страниц.

Ту же самую методику можно применить и для генерации XML в программе - сначала создается объект, заполняется данными, а потом сериализуется в XML.

Если же fb2-файл находится внутри zip-архива, то стандартными средствами .NET можно легко прочитать файл из него. Это почти так же просто, как прочитать обычный текстовый файл.

Да, верно, все это и для java есть. Есть dom парсилки, есть поточные, на любой случай жизни в общем.

Да помню тоже писал свою парсилку FB2. Эх давно было дело.
Странный конечно выбор для тестового проекта, с учетом того что подобных парсеров сейчас как грязи полно - в разных вариациях. Но как говорится - если хочется то почему бы и нет. Тему архивов я думаю пока смысла нет развивать хватит и ZipOutputStream из ava.util.zip. А далее парсинг например Fb2Parser ом. Интересно было бы - чтобы проект в итоге получился под мобильные устройства так как под виндой сейчас мало кто читает. А еще было бы супер заточить проект под какую то читалку с электронными чернилами - чтобы еще и апи читалки использовались - стирание экрана через определенное число страниц, регулировка шрифта,...

Изначально мой проект - каталогизатор, который я писала под собственные нужды. Накопилась огромная библиотека электронных книг. Когда хочу чего-нибудь почитать, не могу вспомнить, зачем я когда-то скачивала или покупала ту или иную книгу, и что меня в свое время вдохновило на это. Иными словами, пропадала мотивация читать к тому моменту, когда появлялось время на чтение. Надо было с этим что-то делать. Вот и возникла идея сделать программу чисто под мои собственные запросы. Вот прям в голове была картинка, что и как я хочу, и ничего другого не предлагать) Программу написала, давно пользуюсь. А читалки недавно решила дописать, причем попроще. Чисто для удобства, чтобы сразу из каталога можно было книгу открыть. Но чувствую, что буду улучшать по мере сил и свободного времени. Комментарии с Хабра вдохновляют на это)

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

Судя по гитхабу, последний коммит был 10 лет назад О_о
Оно точно еще собирается/работает на современных системах?

О, да, почему-то спутал с calibre https://calibre-ebook.com/ru/download_windows сейчас она у меня, видимо раньше рулиб использовал, вот и осталась в памяти.

В любом случае, охоту писать что-то свое эти программки как-то отбили. Со всем что мне от каталогизатора книг требуется она справляется, и пользоваться достаточно удобно.

Посмотрю) Теперь уже чтобы позаимствовать фишечки)

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

ага, да еще и все на разных SSD. Жалко терять время на поиски нужной информации. А еще обидно, если когда-то прочитала полезную книгу нон-фикшн, а через неделю в голове остается только 25%, а еще через месяц вообще только смутное воспоминание. Теперь я могу написать небольшой конспект и положить в папку с книжкой. И ничего не пропадает и не забывается)

Все потому, что 99% работы по созданию читалки, это создание способа разбора битых fb2, коих в "этих самых интернетах" - пусть и не подавляющее, но большинство. Даже на "этих ваших литресах" соответствие не всегда достигает 80%.

А откуда вообще берутся эти битые fb2? Софт для их создания, емнип, по пальцам одной руки пересчитать можно. Не руками же в блокноте их делают.

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

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

Вполне собирается и работает, собирал на Debian 11, с незначительными правками.

Сразу в глаза бросилось, что вы 2 раза вычитываете файл, для определение кодировки и потом для чтения. Зачем? читайте сразу в массив байтов или тот же ByteArrayOutputStream, скармливая данные декодеру пока не определит, дальше дочитываете до конца файла и возвращаете new String(bytes, charset)
Так же, возможно, можно упростить работу с картинками, без необходимости их сохранять в файлы, если вы используете html view. Тег img, позволяет это, в такой формате: <img src="data:image/gif;base64,R0lG....

Спасибо) Попробую сделать, как вы советуете.

Хорошо что написали свою реализацию и статью с инструкцией. Жалко что большинство комментариев в стиле -" я такой умный, меня не ценят, все сделано не правильно".

Спасибо, что оценили мою статью! А комментарии помогли мне многое улучшить в моем проекте)

Sign up to leave a comment.

Articles