【文件格式探究】EP.1 对ePub文件格式的初探

这是”文件格式探究”专题的第 1 期——初探 “ePub” 文件格式。这个专题将会给各位读者呈现笔者探索各种文件格式的过程,具体则是文件的内容是 如何呈现出来的。原则上我们假定仅对于这些文件格式的 用途有所了解,但具体实现的细节并不清楚 (如果提前掌握了部分内容,笔者全当其不存在) 。探究过程中我们会尝试使用各种方法来逐渐初步掌握其概貌。

文件格式简介

根据维基百科大陆简体版本的相关描述:

EPub 是一个自由的开放标准,属于一种可以”自动重新排版”的内容;也就是文字内容可以根据阅读设备的特性,以最适于阅读的方式显示。

之所以后面不截是因为再截就剧透了。简单来说,ePub 就是类似于 PDF 那样的”文档型”文件格式,常用于分发电子读物等。

探究过程

环境

现在笔者手头上有一份用于测试的 ePub 文件,文件路径为 ~/Downloads/咖啡馆推理事件簿系列(全四本).epub (趁机夹带私货,反正很合我胃口就是了) ,后续所有的探究活动均建立于此文件上。笔者目前的操作系统环境为 Manjaro 21.1.0 on amd64,终端环境为 GNU bash 5.1.8(1)-release 。为了方便,我们先把文件改个名字 (那你还把原来的名字给出来干嘛?!) :

[littleye233@lymjrolt Downloads]$ cd ~
[littleye233@lymjrolt ~]$ cd Downloads
[littleye233@lymjrolt Downloads]$ mv 咖啡馆推理事件簿系列(全四本).epub test.epub
[littleye233@lymjrolt Downloads]$ ll test.epub
-rw-r--r-- 1 littleye233 littleye233 1253964 Aug 22 23:24 test.epub

Round I. 文件类型

首先我们先尝试用 Linux 系统的内置命令 file 试试水,看看会输出什么东西。键入 file test.epub后执行:

[littleye233@lymjrolt Downloads]$ file test.epub
test.epub: EPUB document EPUB document

哎呀,真可惜! file 命令几乎什么有效信息都没给我们。 file 命令的 man 页面明确给出此命令可以判断文件格式,但其实它能做到的有很多,例如如果对一个图片文件使用 file ,可能会出现类似下面的结果:

[littleye233@lymjrolt Downloads]$ file ~/.local/share/osu/screenshots/osu_2021-08-21_23-40-03.png
/home/littleye233/.local/share/osu/screenshots/osu_2021-08-21_23-40-03.png: PNG image data, 1920 x 961, 8-bit/color RGBA, non-interlaced

这样我们可以通过 file 中提供的相关信息顺藤摸瓜,尝试在文件的二进制编码内容中寻找其蛛丝马迹,进而推测对应”位点”所表达的含义 (因为一些文件格式要求在特定的位置表达某些含义) ,如果能提供类似注释的信息就再好不过了。

Round II. 文件结构

现在我们回到这个 ePub 文件上来。现在我们尝试能否直接获取其内容,目的是通过文件头部的部分 可见字符猜测其文件结构。输入 nano test.epub 直接预览,或使用 head --bytes=120 test.epub 查看前面 120 个字节的内容:

[littleye233@lymjrolt Downloads]$ head --bytes=120 test.epub
PK!oa�mimetypeapplication/epub+zipPU�N�;�ʯ�META-INF/container.xml]�A
�0E�=

果不其然,我们看到了一些有趣的字眼: “mimetypeapplication/epub+zip” ,凭经验猜测,这应该是 ePub 文件格式的文件头,而其中的 “zip” 也说明—— ePub 文件可能本质上就是一个压缩档。

其实很多文件格式 (例如 Word 文档 “*.docx”) 其本质都是在一个压缩档中加入各种资源文件和配置文件,只要有对应的软件进行读取并重新加工,用户即能看到效果。

Round III. 目录树结构

现在我们可以使用解压缩程序解出 ePub 文件中的内容了。在终端中执行 unzip -l test.epub

[littleye233@lymjrolt Downloads]$ unzip -l test.epub
Archive:  test.epub
  Length      Date    Time    Name
  2422768                     72 files

同时可以直接解压:

[littleye233@lymjrolt Downloads]$ unzip test.epub -d test_epub
Archive:  test.epub
 extracting: test_epub/mimetype
  inflating: test_epub/META-INF/container.xml
  inflating: test_epub/OEBPS/content.opf
  inflating: test_epub/OEBPS/Images/cover00464.jpeg
  inflating: test_epub/OEBPS/Images/image00456.jpeg
  inflating: test_epub/OEBPS/Images/image00457.jpeg
  inflating: test_epub/OEBPS/Images/image00458.jpeg
  inflating: test_epub/OEBPS/Images/image00459.jpeg
  inflating: test_epub/OEBPS/Images/image00460.jpeg
  inflating: test_epub/OEBPS/Images/image00461.jpeg
  inflating: test_epub/OEBPS/Images/image00462.jpeg
  inflating: test_epub/OEBPS/Images/image00463.jpeg
  inflating: test_epub/OEBPS/Styles/style0001.css
  inflating: test_epub/OEBPS/Styles/style0002.css
  inflating: test_epub/OEBPS/Styles/style0003.css
  inflating: test_epub/OEBPS/Styles/style0004.css
  inflating: test_epub/OEBPS/Styles/style0005.css
  inflating: test_epub/OEBPS/Styles/style0006.css
  inflating: test_epub/OEBPS/Styles/style0007.css
  inflating: test_epub/OEBPS/Styles/style0008.css
  inflating: test_epub/OEBPS/Styles/style0009.css
  inflating: test_epub/OEBPS/Text/cover_page.xhtml
  inflating: test_epub/OEBPS/Text/part0000.xhtml
  inflating: test_epub/OEBPS/Text/part0001.xhtml
  inflating: test_epub/OEBPS/Text/part0002.xhtml
  inflating: test_epub/OEBPS/Text/part0003.xhtml
  inflating: test_epub/OEBPS/Text/part0004.xhtml
  inflating: test_epub/OEBPS/Text/part0005.xhtml
  inflating: test_epub/OEBPS/Text/part0006.xhtml
  inflating: test_epub/OEBPS/Text/part0007.xhtml
  inflating: test_epub/OEBPS/Text/part0008.xhtml
  inflating: test_epub/OEBPS/Text/part0009.xhtml
  inflating: test_epub/OEBPS/Text/part0010.xhtml
  inflating: test_epub/OEBPS/Text/part0011.xhtml
  inflating: test_epub/OEBPS/Text/part0012.xhtml
  inflating: test_epub/OEBPS/Text/part0013.xhtml
  inflating: test_epub/OEBPS/Text/part0014.xhtml
  inflating: test_epub/OEBPS/Text/part0015.xhtml
  inflating: test_epub/OEBPS/Text/part0016.xhtml
  inflating: test_epub/OEBPS/Text/part0017.xhtml
  inflating: test_epub/OEBPS/Text/part0018.xhtml
  inflating: test_epub/OEBPS/Text/part0019.xhtml
  inflating: test_epub/OEBPS/Text/part0020.xhtml
  inflating: test_epub/OEBPS/Text/part0021.xhtml
  inflating: test_epub/OEBPS/Text/part0022.xhtml
  inflating: test_epub/OEBPS/Text/part0023.xhtml
  inflating: test_epub/OEBPS/Text/part0024.xhtml
  inflating: test_epub/OEBPS/Text/part0025.xhtml
  inflating: test_epub/OEBPS/Text/part0026.xhtml
  inflating: test_epub/OEBPS/Text/part0027.xhtml
  inflating: test_epub/OEBPS/Text/part0028.xhtml
  inflating: test_epub/OEBPS/Text/part0029.xhtml
  inflating: test_epub/OEBPS/Text/part0030.xhtml
  inflating: test_epub/OEBPS/Text/part0031.xhtml
  inflating: test_epub/OEBPS/Text/part0032.xhtml
  inflating: test_epub/OEBPS/Text/part0033.xhtml
  inflating: test_epub/OEBPS/Text/part0034.xhtml
  inflating: test_epub/OEBPS/Text/part0035.xhtml
  inflating: test_epub/OEBPS/Text/part0036.xhtml
  inflating: test_epub/OEBPS/Text/part0037.xhtml
  inflating: test_epub/OEBPS/Text/part0038.xhtml
  inflating: test_epub/OEBPS/Text/part0039.xhtml
  inflating: test_epub/OEBPS/Text/part0040.xhtml
  inflating: test_epub/OEBPS/Text/part0041.xhtml
  inflating: test_epub/OEBPS/Text/part0042.xhtml
  inflating: test_epub/OEBPS/Text/part0043.xhtml
  inflating: test_epub/OEBPS/Text/part0044.xhtml
  inflating: test_epub/OEBPS/Text/part0045.xhtml
  inflating: test_epub/OEBPS/Text/part0046.xhtml
  inflating: test_epub/OEBPS/Text/part0047.xhtml
  inflating: test_epub/OEBPS/Text/part0048.xhtml
  inflating: test_epub/OEBPS/toc.ncx

为了更清楚地显示文件树结构,我们也可以使用 tree 命令 (这个命令在 Windows 中是内置的,在 Linux 中需要安装 tree 这个包,使用软件包管理器或编译安装均可) :

[littleye233@lymjrolt test_epub]$ tree
.
├── META-INF
│   └── container.xml
├── mimetype
└── OEBPS
    ├── content.opf
    ├── Images
    │   ├── cover00464.jpeg
    │   ├── image00456.jpeg
    │   ├── image00457.jpeg
    │   ├── image00458.jpeg
    │   ├── image00459.jpeg
    │   ├── image00460.jpeg
    │   ├── image00461.jpeg
    │   ├── image00462.jpeg
    │   └── image00463.jpeg
    ├── Styles
    │   ├── style0001.css
    │   ├── style0002.css
    │   ├── style0003.css
    │   ├── style0004.css
    │   ├── style0005.css
    │   ├── style0006.css
    │   ├── style0007.css
    │   ├── style0008.css
    │   └── style0009.css
    ├── Text
    │   ├── cover_page.xhtml
    │   ├── part0000.xhtml
    │   ├── part0001.xhtml
    │   ├── part0002.xhtml
    │   ├── part0003.xhtml
    │   ├── part0004.xhtml
    │   ├── part0005.xhtml
    │   ├── part0006.xhtml
    │   ├── part0007.xhtml
    │   ├── part0008.xhtml
    │   ├── part0009.xhtml
    │   ├── part0010.xhtml
    │   ├── part0011.xhtml
    │   ├── part0012.xhtml
    │   ├── part0013.xhtml
    │   ├── part0014.xhtml
    │   ├── part0015.xhtml
    │   ├── part0016.xhtml
    │   ├── part0017.xhtml
    │   ├── part0018.xhtml
    │   ├── part0019.xhtml
    │   ├── part0020.xhtml
    │   ├── part0021.xhtml
    │   ├── part0022.xhtml
    │   ├── part0023.xhtml
    │   ├── part0024.xhtml
    │   ├── part0025.xhtml
    │   ├── part0026.xhtml
    │   ├── part0027.xhtml
    │   ├── part0028.xhtml
    │   ├── part0029.xhtml
    │   ├── part0030.xhtml
    │   ├── part0031.xhtml
    │   ├── part0032.xhtml
    │   ├── part0033.xhtml
    │   ├── part0034.xhtml
    │   ├── part0035.xhtml
    │   ├── part0036.xhtml
    │   ├── part0037.xhtml
    │   ├── part0038.xhtml
    │   ├── part0039.xhtml
    │   ├── part0040.xhtml
    │   ├── part0041.xhtml
    │   ├── part0042.xhtml
    │   ├── part0043.xhtml
    │   ├── part0044.xhtml
    │   ├── part0045.xhtml
    │   ├── part0046.xhtml
    │   ├── part0047.xhtml
    │   └── part0048.xhtml
    └── toc.ncx

5 directories, 72 files

Round IV. 内部文件

到这里我们大概就能猜出来:

  • META-INF 文件夹:里面存放的应该是”容器” (也就是这个 ePub 文件) 的相关配置文件;
  • mimetype 文件:里面定义了这个文件的类型为 “ePub” (其中 “MIME” 是 “Multipurpose Internet Mail Extensions” 的缩写,从字面上也能看出其具有指示 “Extension” 的机能) ;
  • OEBPS 文件夹:虽暂不知其确切含义,但应存放 ePub 的文字、图片以及其他的界面数据;
  • content.opf 文件:里面存放的应该是目录信息——或是定义各种文件的”次序”;
  • Images StylesText 文件夹:明显分别存放图片、层叠样式表和文字数据;
  • toc.ncx 文件:可能是真正的目录 (“toc” 是 “table of contents” 的缩写)。

接下来我们将挨个分析。

Round IV.I. 容器

先看 META-INF/container.xml

[littleye233@lymjrolt test_epub]$ file META-INF/container.xml
META-INF/container.xml: XML 1.0 document, ASCII text

输出其内容:


显然是一个标准的 XML 文件,其中我们可以注意到 /container/rootfiles/rootfile[@class='full-path'][1] 中定义了一个我们之前认定的目录文件,但此处可以规范化,故这个文件在大多数 ePub 档中应该是相同的。

Round IV.II. 文件类型定性

接下来看 mimetype 文件:

[littleye233@lymjrolt test_epub]$ cat mimetype
application/epub+zip

这也是相当显然的,也不再赘述。

Round IV.III. 目录?

再看 OEBPS/content.opf

[littleye233@lymjrolt test_epub]$ file OEBPS/content.opf
OEBPS/content.opf: XML 1.0 document, Unicode text, UTF-8 text, with very long lines (504)

这也是一个 XML 文件,令人惊讶的是 file 命令竟能看出这个文件中最长的行有 504 个字符,属实让人害怕。

点此查看 OEBPS/content.opf 的全部内容 (已经过格式化)


    咖啡馆推理事件簿系列(全四本)
    zh
    3899198450
    (日)冈崎琢磨
    2018-03-15

说明我之前并没有猜错,这个文件存放的是超越”目录”的东西,而是”次序”——更进一步说。是”索引”。这个文件类似于其他文件格式或目录树中的 index.* ,将 ePub 中的各种数据编上号码,同时这里也定义了标题、语言、作者、出版 (发布) 日期等元信息。至于之前看到的超长行,似乎是一种十六进制的水印 (watermark) ,或许是为了防侵权等。

其中的 /package/manifest/item 定义了所有的索引,以及文件对应的类型; /package/spine/itemref 暂不知进一步的作用,但从中可看出能定义是否”线性” (linear) ; /package/guide/reference 定义了 ePub 的封面等索引,可供文件管理器和 ePub 阅读器使用 (显示预览页) 。

Round IV.IV. 目录!

再看 OEBPS/toc.ncx

[littleye233@lymjrolt test_epub]$ file OEBPS/toc.ncx
OEBPS/toc.ncx: XML 1.0 document, Unicode text, UTF-8 text

感觉再讨论文件类型已经无关紧要了。再次查看内容:

点此查看 OEBPS/toc.ncx 的全部内容 (已经过格式化)


    咖啡馆推理事件簿系列(全四本)

        总目录

        咖啡馆推理事件簿:下次见面时,请让我品尝你煮的咖啡

          序章

          一 事件始于第二次光顾

          二 Bittersweet Black

          三 隐藏在乳白色中的心

          四 棋盘上的狩猎

          五 past,present,f******?

          六 Animals in the closed room

          七 下次见面时,请让我品尝你煮的咖啡

          终章

        咖啡馆推理事件簿2:她梦到了欧蕾咖啡

          序曲 她的梦

          第一章 敬启致未来的你

          第二章 狐狸的迷惑

          第三章 打碎乳白色的心

          第四章 咖啡侦探蕾拉事件簿

          第五章 (She Wanted To Be)WANTED

          第六章 the Sky Occluded in the Sun

          第七章 在星空之下同命相连

          终章 她梦到了欧蕾咖啡

        咖啡馆推理事件簿3:扰人心神的咖啡

          序曲 五年前

          第一章 参加大赛

          第二章 前夜

          第三章 第一天

          第四章 第二天

          第五章 真相

          第六章 日后

          尾声 五年前

        咖啡馆推理事件簿4:休闲时光的五种风味

          午后三点前的无聊风景

          帕列塔之恋

          消失的礼物飞镖

          可视化的原生艺术

          在塔列兰咖啡馆的庭院里

          特别篇 如释重负

我们不妨将目光转向较为重要的”目录”的定义上。为了方便观察,笔者偷点懒,使用桌面环境中自带的阅读器观察:

【文件格式探究】EP.1 对ePub文件格式的初探

从中可以看出目录是二层结构,恰好和 OEBPS/toc.ncx 中的定义保持一致。而其中的部分重要属性均可”望文生义”,此处不再进一步研究。

Round IV.V. 其余部分

最后剩下的是图片、文字和层叠样式表。虽然这部分是在整个 ePub 文件中占比最大也可以说是最重要的部分,但由于这一块的内容实在是太过直白,再讲下去恐怕要开始补习 HTML 和 CSS 知识了,故同样略去。

总结

根据上文中的简要探究, ePub 是一种以 XML 文件格式为配置文件类型的、包含有图片及文字等数据的、以压缩档为本质的文件格式。查阅相关资料后可知其实质与上文中分析类似。

而通过上文的分析,我们初步体验到分析一种陌生文件格式的规律和技巧,可以用于后续对更复杂的文件格式的探究。

但最后,别忘了把那个 ePub 文件的名字改回来 XD :

[littleye233@lymjrolt Downloads]$ mv test.epub 咖啡馆推理事件簿系列(全四本).epub

【完】

脚注

Original: https://www.cnblogs.com/littleye233/p/15178306.html
Author: 小叶Little_Ye
Title: 【文件格式探究】EP.1 对ePub文件格式的初探

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/606382/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 【抄】Shell正则表达式

    shell 正则语法基础 copy from: https://man.linuxde.net/docs/shell_regex.html 正则表达式的分类 基本的正则表达式(Ba…

    Linux 2023年5月28日
    093
  • Jenkins发布SpringBoot项目

    第二步:Configure System (系统设置) 我们只需要设置最后面的一项,配置远程服务SSH: 配置完成后点击保存即可,为后面我们配置自动化部署做准备,配置如下图: 第三…

    Linux 2023年6月14日
    086
  • OpenSSH制作rpm包和升级OpenSSH过程中遇到的问题

    百度网盘:https://pan.baidu.com/s/1gqpH2xeOkYHJ0CiztbmqoQ 提取码:imfg cp x11-ssh-askpass-1.2.4.1.t…

    Linux 2023年6月7日
    081
  • redis查看状态信息

    redis查看状态信息 info all|default Info 指定项 server服务器信息 redis_version : Redis 服务器版本 redis_git_sh…

    Linux 2023年5月28日
    087
  • 基础算法题

    Problem 3或5的倍数 2: 偶斐波那契数 4:最大回文乘积 5 窗口移动 11:方向数组 13大整数加法 、 14最长考拉兹序列 15:网格路径 25:1000位斐波那契数…

    Linux 2023年6月7日
    093
  • 这里聊聊扫地机的 IOT 开发

    以下内容为本人的著作,如需要转载,请声明原文链接微信公众号「englyf」 https://mp.weixin.qq.com/s/Xszi1YFxVqpJ7OcOt-lrqw 消费…

    Linux 2023年6月6日
    0100
  • 你的团队工作量饱和吗?

    参与软件开发的相关人员,虽然称为工程技术人员,但本质上其实就是手艺人。手艺嘛肯定是一技之长,里面多少有些门道,外行人做不了, 也很难完全搞清楚其中的门道,合作过程中就怕被坑上当 :…

    Linux 2023年6月13日
    079
  • 什么是可调CAP策略?为什么需要可调CAP策略?

    在说可调CAP策略之前,我们要先说说CAP理论。 CAP理论是设计分布式系统必用的黄金法则,它提出了设计分布式系统的三个基本要求:一致性(Consistency)、可用性(Avai…

    Linux 2023年6月6日
    0104
  • 最小生成树-Prim算法

    最小生成树minimal-spanning-tree(概念就不具体介绍了)有两种基于不同贪心选择的算法,一个为Prim算法,一个为Kruskal算法。 Prim和Dijkstra算…

    Linux 2023年6月7日
    084
  • HTTPS 通信过程

    posted @2021-11-26 21:23 HOsystem 阅读(27 ) 评论() 编辑 Original: https://www.cnblogs.com/HOsyst…

    Linux 2023年6月13日
    0139
  • docker 启动mysql

    创建配置文件 mysqld.cnf Original: https://www.cnblogs.com/outsrkem/p/15704614.htmlAuthor: Outsrk…

    Linux 2023年6月6日
    061
  • 在VS code使用Remote-SSH远程连接Linux 开发C++ 配置详细介绍

    VS code 远程连接服务器,编译C++ 一、前期准备 1、VS code安装 Remote-SSH插件 2、Windows安装SSH。 3、Linux服务器连接测试。 a.接通…

    Linux 2023年5月27日
    0136
  • Python导入cx_Oracle报错

    系统环境:RHEL5.4 python2.5(手动编译安装,系统带有2.4版本) 在使用python脚本访问数据库时,需要导入cx_Oracle模块 $>>>im…

    Linux 2023年6月14日
    079
  • [ Terminal ] 在 Windows Terminal 中使用 Git Bash

    https://www.cnblogs.com/yeungchie/ Git 自带的 git-bash 太简陋了,ConEmu 又太卡了,还是这个 Windows Terminal…

    Linux 2023年6月7日
    095
  • SpringBoot中通过AOP整合日志文件

    1.SpringBoot中通过AOP整合日志文件 1. 导入相关的依赖 org.springframework.boot spring-boot-starter org.sprin…

    Linux 2023年6月14日
    083
  • shell多线程运行程序

    #!/bin/bash function my_cmd(){ sleep 1 } date tmp_fifofile="/tmp/$$.fifo" mkfifo…

    Linux 2023年6月6日
    0104
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球