日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用itext为已有的pdf文档生成书签

發(fā)布時(shí)間:2023/12/29 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用itext为已有的pdf文档生成书签 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

代碼具有很強(qiáng)的局限性,并不適合所有的電子書目錄。代碼生成目錄主要是針對(duì)于 《啊哈!算法》,其他的目錄結(jié)構(gòu)可能生成結(jié)果不符合預(yù)期。

有些時(shí)候我們下載的電子書沒有書簽,雖然不影響閱讀,但是使用體驗(yàn)很差,尤其是需要跳轉(zhuǎn)時(shí)。因?yàn)橹霸陧?xiàng)目中也是用過itext用于生成企業(yè)的信用報(bào)告(圖片,目錄,水印,錨點(diǎn)),所以相對(duì)來說比較熟悉些,看過官網(wǎng)的文檔也知道可以實(shí)現(xiàn)。然后就在網(wǎng)上找了些demo試著使用itext生成書簽,解放雙手。

準(zhǔn)備

該版本比較簡(jiǎn)單,局限性特別大,只能識(shí)別特定的簡(jiǎn)單目錄結(jié)構(gòu)。

引入依賴
<dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.11</version> </dependency>
獲取PDF文檔的目錄

在當(dāng)當(dāng)上或者京東等網(wǎng)站上找到對(duì)應(yīng)的書籍,在商品介紹里面一般都會(huì)提供書籍的目錄信息。復(fù)制目錄,并對(duì)目錄做一些小的處理。

  • 復(fù)制的目錄中的空格是中文空格,需要將所有的中文空格修改為英文空格。當(dāng)然也可以使用中文空格(代碼需要修改)
  • 為了操作方便,刪除了“目錄”文本部分。當(dāng)然也可以對(duì)目錄頁也添加對(duì)應(yīng)的頁碼關(guān)系
  • 需要手動(dòng)的找出文檔正文的起始頁碼。 比如啊哈!算法的正文是第13頁。
  • 如果想要把目錄也放在文件中,需要進(jìn)行文本轉(zhuǎn)碼(utf-8)。Windows記事本的轉(zhuǎn)碼的utf8文件實(shí)際上是utf-8-bom ,這種格式是不對(duì)的。
  • 啊哈!算法。 文本中帶目錄對(duì)應(yīng)頁碼信息的的文本。注意需要手動(dòng)的找出目錄對(duì)應(yīng)的實(shí)際頁數(shù)

    目錄 11 第1章 一大波數(shù)正在靠近——排序 1第1節(jié) 最快最簡(jiǎn)單的排序——桶排序 2第2節(jié) 鄰居好說話——冒泡排序 7第3節(jié) 最常用的排序——快速排序 12第4節(jié) 小哼買書 20..............................

    spring源碼解析的目錄

    第一部分 核心實(shí)現(xiàn)第1章 Spring整體架構(gòu)和環(huán)境搭建 2 1.1 Spring的整體架構(gòu) 2 1.2 環(huán)境搭建 4 1.2.1 安裝GitHub 4 1.2.2 安裝Gradle 5 1.2.3 下載Spring 6第2章 容器的基本實(shí)現(xiàn) 10 2.1 容器基本用法 10 2.2 功能分析 11 2.3 工程搭建 12 。。。。。。。。。。.。。。。

    代碼針對(duì)了這兩種格式的目錄文件(嗯,第二種沒有測(cè)試,可能有問題)。

    生成書簽

    下面以啊哈!算法的書簽生成為例

    手動(dòng)的找到正文的實(shí)際頁碼,即“第1章 一大波數(shù)正在靠近——排序 1 ”是第13頁。

    代碼

    注意需要對(duì)目錄文件進(jìn)行utf8轉(zhuǎn)碼(utf8-no-bom),utf8轉(zhuǎn)碼,utf8轉(zhuǎn)碼,utf8轉(zhuǎn)碼,utf8轉(zhuǎn)碼,可以使用editplus等文本編輯工具來修改編碼。Windows記事本的轉(zhuǎn)碼是utf-8-with-bom。

    不進(jìn)行轉(zhuǎn)碼的話,書簽會(huì)生成失敗。因?yàn)橄旅娲a永不執(zhí)行。因?yàn)槭褂肐DE工具會(huì)發(fā)現(xiàn),
    sectionNumberStr實(shí)際上等于"\ufeff目錄"。這是因?yàn)镸icrosoft 建議所有的 Unicode 文件應(yīng)該以 \uFEFF 字符開頭,作為標(biāo)記字節(jié)順序存儲(chǔ)的標(biāo)記。標(biāo)準(zhǔn)的utf8編碼是不需要設(shè)置 這個(gè)字節(jié)順序標(biāo)記。

    else if("目錄".equals(sectionNumberStr)){ }

    該方式需要傳入目錄對(duì)應(yīng)的實(shí)際頁碼。

    目錄 11 第1章 一大波數(shù)正在靠近——排序 1第1節(jié) 最快最簡(jiǎn)單的排序——桶排序 2第2節(jié) 鄰居好說話——冒泡排序 7第3節(jié) 最常用的排序——快速排序 12第4節(jié) 小哼買書 20 import com.itextpdf.text.Document; import com.itextpdf.text.DocumentException; import com.itextpdf.text.pdf.*; import java.io.BufferedReader; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern;public class GenerateBookmarkUtil {private Pattern spacePattern = Pattern.compile("\\s*");public static void main(String[] args) {GenerateBookmarkUtil zcc = new GenerateBookmarkUtil();String sourceDocPath = "E:\\BaiduNetdiskDownload\\啊哈!算法.pdf"; //電子書路徑String sourceTextPath = "C:\\Users\\Administrator\\Desktop\\aha.txt";//生成的目錄文本路徑String desFilename = "D:\\testhaha1.pdf"; // 生成的帶有目錄的文件的路徑(問價(jià)是復(fù)制,不是覆蓋)try {zcc.createPdf(sourceTextPath, sourceDocPath, desFilename,13);} catch (DocumentException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}/***@param sTxtPath 書簽文件的路徑*@param sPdfPath 需要生成書簽的文件*@param filename 生成書簽后的文件路徑*@param startPage 正文的實(shí)際頁數(shù)-1*/public void createPdf(String sTxtPath, String sPdfPath, String filename,int startPage) throws DocumentException, IOException {if(startPage>0)startpage--;//可以創(chuàng)建新的文件,也可以直接操作源文件,添加書簽// step 1Document document = new Document();// step 2 輸出文件PdfCopy writer = new PdfCopy(document, new FileOutputStream(filename)); // step 3writer.setViewerPreferences(PdfWriter.PageModeUseOutlines);//設(shè)置打開pdf文件時(shí)顯示書簽document.open();// step 4 逐頁讀入pdf文件并寫入輸出文件PdfReader reader = new PdfReader(sPdfPath);int n = reader.getNumberOfPages();for (int page = 1; page <= n; page++) {writer.addPage(writer.getImportedPage(reader, page));}writer.freeReader(reader);// step 5 添加書簽PdfOutline root = writer.getRootOutline();PdfAction action;//標(biāo)識(shí)書簽點(diǎn)擊后的跳轉(zhuǎn)動(dòng)作,通過它設(shè)置跳轉(zhuǎn)的頁碼try {//讀入保存書簽的TXT文件,分拆為書簽名及跳轉(zhuǎn)頁碼;BufferedReader bufRead = new BufferedReader(new FileReader(sTxtPath));String str;String[] ss = null;int skipPage = startPage; //正文書簽跳過的頁數(shù)/*數(shù)據(jù)的存儲(chǔ)結(jié)構(gòu)** page 頁碼*title 標(biāo)題* kids 子書簽 page,title ,kids*/List<Map<String, Object>> outlines = new ArrayList<>();//存放解析的數(shù)據(jù)String pageNumStr = null;int pageNum = 0;//遍歷讀取目錄文件,每次讀取一行,并解析出該行的標(biāo)題和頁碼值 while ((str = bufRead.readLine()) != null) {String title = "";int parentPage = 0;String childTitle = "";int childPage = 0;str = str.trim();//過濾空行Matcher matcher = spacePattern.matcher(str);if (matcher.matches()) {continue;}//獲取頁碼ss = str.split(" ");pageNumStr = ss[ss.length - 1].trim();//不包含頁碼的標(biāo)題for (int j = 0; j < ss.length - 1; j++) {title += ss[j] + " ";}if (pageNumStr.matches("\\d+")) {//存在頁碼try {pageNum = Integer.valueOf(pageNumStr);pageNum += skipPage;} catch (Exception e) {}String category="目錄";String sectionNumberStr = ss[0]; //獲取標(biāo)題的序號(hào)if (sectionNumberStr.contains("章")) {//章節(jié)List<Map<String, Object>> kids = null;kids = new ArrayList();Map<String, Object> chapterMap = new HashMap<>();chapterMap.put("title", title);chapterMap.put("page", pageNum);chapterMap.put("kids", kids);outlines.add(chapterMap);}else if("目錄".equals(sectionNumberStr)){//目錄書簽new PdfOutline(root,PdfAction.gotoLocalPage(pageNum-skipPage, new PdfDestination(PdfDestination.FIT), writer), "目 錄");}else {//小節(jié)List<Map<String, Object>> kids = (List<Map<String, Object>>) outlines.get(outlines.size() - 1).get("kids");//將小節(jié)添追加到自書簽列表Map<String, Object> littleChapter = new HashMap<>();littleChapter.put("title", title);littleChapter.put("page", pageNum);littleChapter.put("kids", new ArrayList<>());kids.add(littleChapter);}} else {//不存在頁碼,可能是大標(biāo)題 或者目錄 例如:第一部分 核心實(shí)現(xiàn)Map<String, Object> bigSection = new HashMap<>();bigSection.put("title", title);bigSection.put("page", -1);bigSection.put("kids", new ArrayList<>());outlines.add(bigSection);}}//數(shù)據(jù)遍歷,添加書簽outlines.forEach(map -> {String sectionTitle = (String) map.get("title");int page = (int) map.get("page");List<Map<String, Object>> kids = (List<Map<String, Object>>) map.get("kids");PdfOutline sectionOutline = null;if (page < 0) {//該部分是大類別int parentPage = (int) kids.get(0).get("page") - 1; //獲取大分類的頁數(shù),一般就是子目錄頁數(shù)減一PdfAction action1 = PdfAction.gotoLocalPage(parentPage,new PdfDestination(PdfDestination.FIT), writer);//設(shè)置書簽動(dòng)作sectionOutline = new PdfOutline(root, action1, sectionTitle, false); //大分類的} else {PdfAction action1 = PdfAction.gotoLocalPage(page,new PdfDestination(PdfDestination.FIT), writer);//設(shè)置書簽動(dòng)作sectionOutline = new PdfOutline(root, action1, sectionTitle, false); //一級(jí)章節(jié)標(biāo)題;}for (Map<String, Object> kid : kids) { //一級(jí)章節(jié)String firstTitle = (String) kid.get("title");int firstPage = (int) kid.get("page");List<Map<String, Object>> firstKids = (List<Map<String, Object>>) kid.get("kids");PdfAction action2 = PdfAction.gotoLocalPage(firstPage,new PdfDestination(PdfDestination.FIT), writer);//設(shè)置書簽動(dòng)作PdfOutline firstOutline = new PdfOutline(sectionOutline, action2, firstTitle, false); //一級(jí)標(biāo)題的outlinefor (Map<String, Object> secondKid : firstKids) {//二級(jí)章節(jié)String secondTitle = (String) kid.get("title");int secondPage = (int) kid.get("page");List<Map<String, Object>> secondKids = (List<Map<String, Object>>) kid.get("kids");PdfAction action3 = PdfAction.gotoLocalPage(secondPage,new PdfDestination(PdfDestination.FIT), writer);//設(shè)置書簽動(dòng)作PdfOutline secondOutline = new PdfOutline(firstOutline, action2, secondTitle, false); //二級(jí)標(biāo)題的outline}}});} catch (IOException ioe) {}document.close();}}

    生成好的書簽。代碼的局限性比較高,可以自定義自己的書簽類

    參考文章:使用itext寫的pdf文件添加書簽的小工具

    總結(jié)

    以上是生活随笔為你收集整理的使用itext为已有的pdf文档生成书签的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。