Epub电子书切割

引言:由于公司存储电子书的格式是.epub。一本电子书加载的时候,如果电子书大的话,全部加载该电子书会非常的消耗时间和资源。非常的不合理。那么现在,将所有电子书按章切分。将拆分的电子书再上传至服务器,用户点击阅读电子书任何一章节,就加载该章节的数据。这里的具体逻辑不细写,主要细写如果切割电子书的过程。

准备

这里我用到了Epublib这个jar包,详细资料参考下方

epublib github

epublib API

maven库搜索 epublib-core ,kxml2

pom文件引入依赖

<!-- https://mvnrepository.com/artifact/nl.siegmann.epublib/epublib-core -->
<dependency><groupId>nl.siegmann.epublib</groupId><artifactId>epublib-core</artifactId><version>3.1</version>
</dependency><!-- https://mvnrepository.com/artifact/net.sf.kxml/kxml2 -->
<dependency><groupId>net.sf.kxml</groupId><artifactId>kxml2</artifactId><version>2.3.0</version>
</dependency>

分析

epub电子书结构

.epub电子书是怎么的结构。我这边下载了一本。我用winrar解压看下。如下图

可以很清楚看见是由xhtml文件组成资源。关于content.opf ,toc.nxc等这些本来就是属于电子书的数据结构文件,可以自行网上查阅。

epublib中book数据结构

epub电子书抽象成epublib中的book 。epublib 中book的数据结构是怎么样子的呢,这里稍微介绍一下,网上确实资料太少了。

Resource数据结构

Resources类中又有一个HashMap,HashMap中的value为Resource,Resource的数据结构如下:

  1. id,href相当于Resources中那个HashMap中的key,可以找到Resource
  2. title 和 originalHref 表资源的名字和起始的href
  3. mediaType 资源的数据类型 inputEncoding 编码格式
  4. data 第一张图片上的.xhtml转string类型,然后再转成字节流的数据

Metadata

Book里的Metadata相当于电子书的头部,可以获取电子书的基本数据,数据结构如下:

Spine

Book中的骨架结构,用来链接Book资源文件,数据结构如下

Resource 与ResourceReference 为关联,SpineReference是ResourceReference的父类。

在设置好Resouces后一定要设置相应的Spine中的Resouce,不然电子书打开,会无法识别。

TableOfContents

Book中目录对应的数据结构。有目录的名字,目录对应的Resource,对应的数据结构如下:

实战

Demo代码如下:

/*** @Description: 按章节切分 电子书* @Author: ouyangkang* @CreateDate: 2018/9/28 17:41* @Param  [url]*/public static void segmentation(String url){try {// 获取网络资源URL urlResource = new URL(url) ;// 打开链接HttpURLConnection conn = (HttpURLConnection) urlResource.openConnection();// 建立链接conn.connect();// 读取电子书流EpubReader epubReader = new EpubReader();// 获取电子书InputStream inputStream = conn.getInputStream();if (inputStream == null){return;}if (epubReader == null){return;}Book book = epubReader.readEpub(inputStream);if (book == null){return;}// 获取电子书目录TableOfContents tableOfContents = book.getTableOfContents();// 电子书章节封装资源List<SpineReference> spineReferences = book.getSpine().getSpineReferences();// 电子书 章节Id 集合List<String> resourceIds = new ArrayList<>(16);// 获取所有资源hrefSet<String> hrefs = (Set<String>) book.getResources().getAllHrefs();// css 资源文件List<String> hrefCss = new ArrayList<>();hrefs.stream().forEach(href -> {if (href.contains(".css")){hrefCss.add(href);}});spineReferences.stream().forEach(spineReference -> {// 获取章节IdresourceIds.add(spineReference.getResourceId());});// 电子书章节资源Resources resources = new Resources();// 写入电子书EpubWriter epubWriter = new EpubWriter();resourceIds.stream().forEach(resourceId -> {// 电子书章节Book bookChapter = new Book();//章节导航Spine spine = new Spine();if (hrefCss.size() > 0){hrefCss.stream().forEach(href -> {resources.add(book.getResources().getByHref(href));});}nl.siegmann.epublib.domain.Resource resource = book.getResources().getById(resourceId);resources.add(resource);// 获取图片资源try {String imageData = new String(resource.getData(),"UTF-8");// 获取图片源List<String> imagesHrefs = getImgSrc(imageData);//添加该章节下的图片资源imagesHrefs.stream().forEach(imagesHref -> {nl.siegmann.epublib.domain.Resource resourceImage = book.getResources().getByHref(imagesHref);resources.add(resourceImage);});//设置电子书资源// 设置电子书导航文件nl.siegmann.epublib.domain.Resource tocResource = book.getResources().getById("ncx");if (tocResource != null){// 发现有的电子书并不存在 toc.ncx 而是以一种toc.xhtml的文件存在if (tocResource.getHref().contains("toc.ncx")) {spine.setTocResource(tocResource);} else {resources.add(tocResource);}}//添加章节资源bookChapter.setResources(resources);// 添加该章节骨架spine.addSpineReference(new SpineReference(book.getResources().getById(resourceId)));bookChapter.setSpine(spine);// 添加该书的所有目录bookChapter.setTableOfContents(tableOfContents);//文件写入地址String path = "D:\\ebook\\"+resourceId+".epub";File file = new File(path);if (!file.getParentFile().exists()){file.getParentFile().mkdir();}epubWriter.write(bookChapter, new FileOutputStream(file));} catch (IOException e) {e.printStackTrace();}finally {conn.disconnect();}});}catch (Exception e){e.printStackTrace();}}/*** 获取img标签中的src值* @param content* @return*/public static List<String> getImgSrc(String content){List<String> list = new ArrayList<String>();//目前img标签标示有3种表达式//<img alt="" src="1.jpg"/>   <img alt="" src="1.jpg"></img>     <img alt="" src="1.jpg">//开始匹配content中的<img />标签Pattern p_img = Pattern.compile("<(img|IMG|image|IMAGE)(.*?)(/>|></img>|>|></image)");Matcher m_img = p_img.matcher(content);boolean result_img = m_img.find();if (result_img) {while (result_img) {//获取到匹配的<img />标签中的内容String str_img = m_img.group(2);//开始匹配<img />标签中的srcPattern p_src = Pattern.compile("(src|SRC|href|HREF)=(\"|\')(.*?)(\"|\')");Matcher m_src = p_src.matcher(str_img);if (m_src.find()) {String str_src = m_src.group(3);if (str_src.contains("Image")){str_src = str_src.substring(str_src.indexOf("I"),str_src.length());}else {str_src = str_src.substring(str_src.indexOf("i"),str_src.length());}list.add(str_src);}//结束匹配<img />标签中的src//匹配content中是否存在下一个<img />标签,有则继续以上步骤匹配<img />标签中的srcresult_img = m_img.find();}}return list;}

转载于:https://www.cnblogs.com/Krloypower/p/9732476.html

Java对epub电子书类型切割相关推荐

  1. 开发EPUB电子书制作下载网站

    角摩网制作EPUB电子书下载地址:http://www.joymo.cn/Html/Diy/wjzz.html,居于epub格式标准,采用C#开发独立的生成程序! EPUB 是一种开放式的数字图书规范 ...

  2. EPUB电子书阅读-MAC版

    EPUB电子书阅读-MAC版 书作为人历史长河中的文化载体,在漫长的发展中,它们以各种各样的形式出现,这其中包括以往的纸质图书和最近几年慢慢流行的电子书籍.在数字信息技术发达的今天,当文字.图片.声音 ...

  3. 教妹学Java(三十二):了解 Java 中的返回类型协变

    你好呀,我是沉默王二,(目前是)CSDN 周排名前十的博客专家.这是<教妹学 Java>专栏的第二十七篇,今天我们来谈谈 Java 中的返回类型协变--Java 的返回值类型支持协变.换句 ...

  4. Epub电子书格式(一)

    做人要厚道:http://blog.sina.com.cn/s/blog_6441e0640100gmfe.html 考虑到amazon提供的KindleGen命令行工具可以转换epub电子书为kin ...

  5. epub 电子书软件代码销售

    epub 电子书软件代码销售 本套代码用来读取epub 格式电子书. 主要面向:有一定开发能力的人员,和有一定制作水平的朋友们. 用途:自己开发学习,钻研,出appstore 应用,卖钱,加广告赚钱等 ...

  6. java不能对什么类型进行转换_关于java:“不兼容类型:void无法转换为…”是什么意思?...

    Java编译消息是什么: "Incompatible types: void cannot be converted to ..." 的意思,以及我该如何解决. 一些编译器使用不同 ...

  7. java泛型之有界类型

    为什么80%的码农都做不了架构师?>>>    在前面的例子中,可以使用任意类替换类型参数.对于大多数情况这很好,但是限制能够传递给类型参数的类型有时是有用的.例如,假设希望创建一个 ...

  8. Java RTTI运行时类型识别

    RTTI(Run-Time Type Identification),通过运行时类型信息程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型. RTTI提供了以下两个非常有用的操作 ...

  9. 【Java基础】基本类型与运算

    Java的8种基本数据类型 8种基本数据类型:byte short int long float double char boolean,基本数据类型不是对象,此类变量在被声明的时候会在栈上分配空间. ...

最新文章

  1. elasticsearch docker无法挂载_使用Docker安装Graylog日志收集系统
  2. slb健康检查方式_SLB健康检查也是“正常”-问答-阿里云开发者社区-阿里云
  3. activiti自己定义流程之整合(五):启动流程时获取自己定义表单
  4. web自动化测试—selenium游览器下拉框操作
  5. Boost:使用Qt加载图像,应用简单的框模糊滤镜
  6. 10、mysql数据表中数据的查询(2)
  7. Android 透明动画实现 详细概述
  8. XILINX FPGA电源设计指南
  9. 传统制造业和工业如何和大数据进行结合
  10. linux yum资源下载,yumdownloader命令 – 从yum存储库下载rpm包
  11. 判断丑数python_263. 丑数(Python)
  12. 电脑扬声器安装程序(UNKNOW)
  13. Python练习_数据类型_day4
  14. Linux权限的理解 | 粘滞位 |权限掩码 |文件类型
  15. c语言链表中next作用,C语言链表中q-next=p;表示什么意思?
  16. ASP.NET EXCEL导入,身份证、手机号长度校验数据校验
  17. 虚拟机中的linux怎么进入命令方式
  18. 2022-2028年中国素食行业竞争策略研究及未来前景展望报告
  19. GoAhead远程命令执行漏洞(CVE-2021-42342)
  20. CommonJs和Es Module的区别

热门文章

  1. 1. 帮贡排序-模拟与高精度(普及/提高-)
  2. P1786 帮贡排序c++良心题解
  3. 草图大师自带模型库在哪里_大师在20分钟或更短的时间内创建您的第一个神经网络模型...
  4. 【星辰傀儡线·命运环·卷一 血鸦】 6 四大长老
  5. 2021年日历记事备忘录(A4可打印版)
  6. 递归案例 ---- 母牛生小牛
  7. Word2003的10个小技巧(转)
  8. Google勇敢新世界:两个天才的相遇
  9. 使用react开发dapp应用实战-宠物认领
  10. 利用Java计算一元二次方程的两个实数根