在项目报告、产品手册、技术规范或合同汇编这类页数较多的 pdf 中,如果没有书签,读者通常只能通过滚动页面或输入页码查找内容。
给 pdf 添加书签后,可以在阅读器侧边栏直接看到文档结构,并快速跳转到指定章节。对于已经存在书签的 pdf,还可能需要修改过时的章节名称,或者删除失效、重复的书签。
本文介绍如何使用 java 操作 pdf 书签,主要包括:
- 为 pdf 添加书签
- 创建多级书签
- 修改已有书签
- 删除指定或全部书签
安装所需的 pdf 库
本文使用 spire.pdf for java 来读取和修改 pdf 文件。它提供了 pdf 书签相关 api,可以添加一级和多级书签,也可以修改或删除现有书签。
如果使用 maven,可以在 pom.xml 中添加官方仓库和依赖。以下以当前官方提供的 12.8.1 版本为例,实际项目可以根据使用时的最新版本进行调整。
<repositories>
<repository>
<id>com.e-iceblue</id>
<name>e-iceblue</name>
<url>https://repo.e-iceblue.cn/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupid>e-iceblue</groupid>
<artifactid>spire.pdf</artifactid>
<version>12.8.1</version>
</dependency>
</dependencies>安装完成后,就可以通过 pdfdocument 加载现有 pdf,并使用书签集合进行后续操作。
为 pdf 添加书签
假设有一份已经生成好的 项目报告.pdf,内容包含:
- 项目概述
- 实施方案
- 数据分析
- 总结建议
可以根据这些章节所在的页面创建书签。
下面的示例分别为前四页添加对应的一级书签:
import com.spire.pdf.pdfdocument;
import com.spire.pdf.pdfpagebase;
import com.spire.pdf.actions.pdfgotoaction;
import com.spire.pdf.bookmarks.pdfbookmark;
import com.spire.pdf.bookmarks.pdftextstyle;
import com.spire.pdf.general.pdfdestination;
import com.spire.pdf.graphics.pdfrgbcolor;
import java.awt.color;
import java.awt.geom.point2d;
public class addpdfbookmarks {
public static void main(string[] args) {
// 创建 pdfdocument 对象
pdfdocument pdf = new pdfdocument();
// 加载 pdf 文件
pdf.loadfromfile("项目报告.pdf");
// 定义书签标题
string[] bookmarktitles = {
"项目概述",
"实施方案",
"数据分析",
"总结建议"
};
// 为前四页添加书签
for (int i = 0; i < bookmarktitles.length; i++) {
pdfpagebase page = pdf.getpages().get(i);
// 添加书签
pdfbookmark bookmark =
pdf.getbookmarks().add(bookmarktitles[i]);
// 设置书签跳转目标
pdfdestination destination =
new pdfdestination(
page,
new point2d.float(0, 0)
);
bookmark.setaction(
new pdfgotoaction(destination)
);
// 设置书签颜色
bookmark.setcolor(
new pdfrgbcolor(
new color(47, 84, 150)
)
);
// 设置为粗体
bookmark.setdisplaystyle(
pdftextstyle.bold
);
}
// 保存结果
pdf.savetofile("添加书签后的项目报告.pdf");
pdf.close();
}
}
这里主要涉及三个步骤。
首先通过:
pdf.getbookmarks().add("项目概述");
在文档的书签集合中创建一个书签。
然后创建 pdfdestination:
pdfdestination destination =
new pdfdestination(
page,
new point2d.float(0, 0)
);
它决定点击书签后跳转到哪一页以及页面中的哪个位置。
最后通过:
bookmark.setaction(
new pdfgotoaction(destination)
);
把跳转动作绑定到书签。
需要注意,pdf.getpages().get(i) 中的页面索引从 0 开始,因此:
get(0) → 第 1 页 get(1) → 第 2 页 get(2) → 第 3 页
如果实际章节不是从第一页开始,只需要把对应的页面索引调整为真实位置即可。
为 pdf 创建多级书签
对于结构较复杂的报告,只使用一级书签可能还不够。
例如“实施方案”下面还包括:
实施方案
├── 实施计划
├── 人员安排
└── 风险控制
这种情况下可以在一级书签下面继续添加子书签。
spire.pdf for java 可以通过 pdfbookmark.add() 在父书签下面创建子书签。
例如:
import com.spire.pdf.pdfdocument;
import com.spire.pdf.pdfpagebase;
import com.spire.pdf.actions.pdfgotoaction;
import com.spire.pdf.bookmarks.pdfbookmark;
import com.spire.pdf.general.pdfdestination;
import java.awt.geom.point2d;
public class addchildbookmarks {
public static void main(string[] args) {
pdfdocument pdf = new pdfdocument();
pdf.loadfromfile("项目报告.pdf");
// 创建一级书签
pdfbookmark parentbookmark =
pdf.getbookmarks().add("实施方案");
// 一级书签跳转到第 2 页
pdfpagebase parentpage =
pdf.getpages().get(1);
pdfdestination parentdestination =
new pdfdestination(
parentpage,
new point2d.float(0, 0)
);
parentbookmark.setaction(
new pdfgotoaction(parentdestination)
);
// 创建子书签:实施计划
pdfbookmark planbookmark =
parentbookmark.add("实施计划");
pdfdestination plandestination =
new pdfdestination(
pdf.getpages().get(1),
new point2d.float(0, 120)
);
planbookmark.setaction(
new pdfgotoaction(plandestination)
);
// 创建子书签:人员安排
pdfbookmark staffbookmark =
parentbookmark.add("人员安排");
pdfdestination staffdestination =
new pdfdestination(
pdf.getpages().get(2),
new point2d.float(0, 0)
);
staffbookmark.setaction(
new pdfgotoaction(staffdestination)
);
// 创建子书签:风险控制
pdfbookmark riskbookmark =
parentbookmark.add("风险控制");
pdfdestination riskdestination =
new pdfdestination(
pdf.getpages().get(3),
new point2d.float(0, 0)
);
riskbookmark.setaction(
new pdfgotoaction(riskdestination)
);
pdf.savetofile("多级书签项目报告.pdf");
pdf.close();
}
}
创建多级书签时,子书签并不是添加到:
pdf.getbookmarks()
而是添加到对应的父书签:
parentbookmark.add("实施计划");
这样才能形成真正的层级结构。
如果 pdf 本身已经按照“章节 → 小节”的方式组织,使用多级书签通常比创建大量平级书签更容易浏览。
修改 pdf 中已有的书签
pdf 使用一段时间后,章节名称可能发生变化。
- 例如原来的:项目方案
- 后来改成:项目实施方案
如果 pdf 页面内容已经更新,但书签仍然是旧名称,就可以直接修改已有书签,而不需要重新创建整个 pdf。
通过 getbookmarks().get() 可以取得指定书签,然后使用 settitle()、setcolor() 和 setdisplaystyle() 修改其属性。
示例:
import com.spire.pdf.pdfdocument;
import com.spire.pdf.bookmarks.pdfbookmark;
import com.spire.pdf.bookmarks.pdftextstyle;
import com.spire.pdf.graphics.pdfrgbcolor;
import java.awt.color;
public class editpdfbookmark {
public static void main(string[] args) {
pdfdocument pdf = new pdfdocument();
// 加载包含书签的 pdf
pdf.loadfromfile("项目报告.pdf");
// 获取第一个书签
pdfbookmark bookmark =
pdf.getbookmarks().get(0);
// 修改书签标题
bookmark.settitle("项目实施方案");
// 修改书签颜色
bookmark.setcolor(
new pdfrgbcolor(
new color(31, 78, 121)
)
);
// 设置为粗体
bookmark.setdisplaystyle(
pdftextstyle.bold
);
// 保存结果
pdf.savetofile("修改书签后的项目报告.pdf");
pdf.close();
}
}
如果只是调整章节名称,一般只需要:
bookmark.settitle("新的章节名称");
颜色和字体样式属于可选设置,可以根据文档的实际需求决定是否修改。
删除 pdf 中指定的书签
如果某个章节已经从 pdf 中删除,对应书签也应该同步清理,否则用户点击后仍可能跳转到已经没有实际意义的位置。
删除一级书签可以使用:
pdf.getbookmarks().removeat(0);
例如删除第一个书签:
import com.spire.pdf.pdfdocument;
public class deletepdfbookmark {
public static void main(string[] args) {
pdfdocument pdf = new pdfdocument();
pdf.loadfromfile("项目报告.pdf");
// 删除第一个一级书签
pdf.getbookmarks().removeat(0);
pdf.savetofile("删除书签后的项目报告.pdf");
pdf.close();
}
}
如果一级书签包含子书签,删除这个一级书签时,其子书签也会一起删除。
删除指定的子书签
如果只需要删除某个章节下的小节,而希望保留父书签,可以先取得父书签,再调用它的 removeat():
pdfbookmark parentbookmark =
pdf.getbookmarks().get(0);
// 删除父书签下的第一个子书签
parentbookmark.removeat(0);
这里删除的是:
一级书签
└── 第一个子书签 ← 删除
而不是整个一级书签。
这种方式适合文档结构发生局部调整的情况。
删除 pdf 中的全部书签
如果需要彻底重建 pdf 的导航结构,可以先删除全部旧书签:
pdf.getbookmarks().clear();
完整示例:
import com.spire.pdf.pdfdocument;
public class deleteallpdfbookmarks {
public static void main(string[] args) {
pdfdocument pdf = new pdfdocument();
pdf.loadfromfile("项目报告.pdf");
// 删除全部书签
pdf.getbookmarks().clear();
pdf.savetofile("无书签项目报告.pdf");
pdf.close();
}
}
clear() 会清空文档的整个书签集合。
这种方式比较适合:
- 原有书签结构已经完全失效
- 需要根据新的目录重新生成书签
- 批量处理来源不同、书签质量不一致的 pdf
实际开发中的几个注意点
1. pdf 页面索引从 0 开始
给书签设置目标页面时,很容易出现页码偏移。
例如业务上说“跳转到第 5 页”,代码实际应该使用:
pdf.getpages().get(4);
如果书签来自数据库或配置文件,而其中存储的是正常的 1-based 页码,可以在代码中统一减 1:
int pageindex = pagenumber - 1;
在批量生成书签时尤其要注意这一点。
2. 添加书签前检查目标页面是否存在
如果书签配置来自外部数据,不要直接假设所有页码都有效。
例如:
int pageindex = 10;
if (pageindex >= 0 &&
pageindex < pdf.getpages().getcount()) {
pdfpagebase page =
pdf.getpages().get(pageindex);
// 创建书签
}
这样可以避免配置中的错误页码导致程序处理失败。
3. 书签标题最好与正文结构保持一致
如果正文标题是:3. 项目实施方案
书签却写成:方案
虽然技术上没有问题,但长文档中会增加理解成本。
对于自动生成的报告,可以直接复用系统中的章节名称来生成书签,而不是另外维护一套名称。
例如:
string[] chapternames = {
"1. 项目概述",
"2. 实施方案",
"3. 数据分析",
"4. 总结建议"
};
这样 pdf 正文、目录和书签结构更容易保持一致。
4. 多级书签不要设置得过深
pdf 书签支持层级结构,但实际使用中层级过多反而不方便浏览。
一般的报告或说明书使用:
章节
└── 小节
或者:
章节
└── 小节
└── 子项
通常已经足够。
如果业务数据本身存在六七层结构,可以考虑只把主要层级放入 pdf 书签,而不是完整复制所有数据层级。
总结
对于页数较多的 pdf,书签能够提供比单纯输入页码更直观的导航方式。
本文介绍了如何使用 java:
- 为 pdf 添加一级书签
- 创建父子结构的多级书签
- 修改已有书签的标题和样式
- 删除指定一级书签或子书签
- 清空 pdf 中的全部书签
在实际项目中,如果 pdf 由系统自动生成,可以在生成文档后根据章节名称和页码同步建立书签;如果是处理已有 pdf,则可以根据新的文档结构修改或重建书签。
这样可以让项目报告、技术文档、说明书等长 pdf 保持更清晰的导航结构,也方便后续维护。
以上就是java结合spire.pdf for java实现为pdf添加、修改和删除书签的详细内容,更多关于java pdf书签操作的资料请关注代码网其它相关文章!
发表评论