亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

使用java為pdf添加書簽的方法(pdf書簽制作)

2019-11-26 15:40:39
字體:
來源:轉載
供稿:網友

由于我經常下載一些pdf格式的電子書,有的時候一些好書下載下來沒有書簽,讀起來感覺沒有整體的感覺,所以決定自己寫一個小工具,將特定格式的文本解析成為書簽,然后保存到pdf格式中。
整體思路是從豆瓣啊、京東啊、當當啊、亞馬遜下面的介紹中可以copy出目錄信息,拿《HTTP權威指南》為例:
目錄的結構如:

復制代碼 代碼如下:

第1章 HTTP 概述 3
1.1 HTTP――因特網的多媒體信使 4
1.2 Web 客戶端和服務器 4
1.3 資源 5
1.3.1 媒體類型 6
1.3.2 URI 7
1.3.3 URL 7
1.3.4 URN 8
1.4 事務 9
1.4.1 方法 9
1.4.2 狀態碼 10
1.4.3 Web 頁面中可以包含多個對象 10
1.5 報文 11
1.6 連接 13

每一行后面都有頁碼,而且是用空格分開的。
處理之后,結果為:

主要的邏輯為:

復制代碼 代碼如下:

package org.fra.pdf.bussiness;

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.IntHashtable;
import com.itextpdf.text.pdf.PdfArray;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfIndirectReference;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfNumber;
import com.itextpdf.text.pdf.PdfObject;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfString;
import com.itextpdf.text.pdf.SimpleBookmark;

public class AddPdfOutLineFromTxt {
    private Stack<OutlineInfo> parentOutlineStack = new Stack<OutlineInfo>();

    public void createPdf(String destPdf, String sourcePdf,
            BufferedReader bufRead, int pattern) throws IOException,
            DocumentException {

        if (pattern != AddBookmarkConstants.RESERVED_OLD_OUTLINE
                &&  pattern != AddBookmarkConstants.RESERVED_NONE
                && pattern != AddBookmarkConstants.RESERVED_FIRST_OUTLINE)
            return;
        // 讀入pdf文件
        PdfReader reader = new PdfReader(sourcePdf);

        List<HashMap<String, Object>> outlines = new ArrayList<HashMap<String, Object>>();
        if (pattern == AddBookmarkConstants.RESERVED_OLD_OUTLINE) {
            outlines.addAll(SimpleBookmark.getBookmark(reader));
        } else if (pattern == AddBookmarkConstants.RESERVED_FIRST_OUTLINE) {
            addFirstOutlineReservedPdf(outlines, reader);
        }

        addBookmarks(bufRead, outlines, null, 0);
        // 新建stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(
                destPdf));

        stamper.setOutlines(outlines);
        stamper.close();
    }

    private void addBookmarks(BufferedReader bufRead,
            List<HashMap<String, Object>> outlines,
            HashMap<String, Object> preOutline, int preLevel)
            throws IOException {
        String contentFormatLine = null;
        bufRead.mark(1);
        if ((contentFormatLine = bufRead.readLine()) != null) {
            FormattedBookmark bookmark = parseFormmattedText(contentFormatLine);

            HashMap<String, Object> map = parseBookmarkToHashMap(bookmark);

            int level = bookmark.getLevel();
            // 如果n==m, 那么是同一層的,這個時候,就加到ArrayList中,繼續往下面讀取
            if (level == preLevel) {
                outlines.add(map);
                addBookmarks(bufRead, outlines, map, level);
            }
            // 如果n>m,那么可以肯定,該行是上一行的孩子,, new 一個kids的arraylist,并且加入到這個arraylist中
            else if (level > preLevel) {
                List<HashMap<String, Object>> kids = new ArrayList<HashMap<String, Object>>();
                kids.add(map);
                preOutline.put("Kids", kids);
                // 記錄有孩子的outline信息
                parentOutlineStack.push(new OutlineInfo(preOutline, outlines,
                        preLevel));
                addBookmarks(bufRead, kids, map, level);
            }
            // 如果n<m , 那么就是說孩子增加完了,退回到上層,bufRead倒退一行
            else if (level < preLevel) {
                bufRead.reset();
                OutlineInfo obj = parentOutlineStack.pop();
                addBookmarks(bufRead, obj.getOutlines(), obj.getPreOutline(),
                        obj.getPreLevel());
            }

        }
    }

    private HashMap<String, Object> parseBookmarkToHashMap(
            FormattedBookmark bookmark) {
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("Title", bookmark.getTitle());
        map.put("Action", "GoTo");
        map.put("Page", bookmark.getPage() + " Fit");
        return map;
    }

    private FormattedBookmark parseFormmattedText(String contentFormatLine) {
        FormattedBookmark bookmark = new FormattedBookmark();
        String title = "";
        String destPage = "";

        // 當沒有頁碼在字符串結尾的時候,一般就是書的名字,如果格式正確的話。
        int lastSpaceIndex = contentFormatLine.lastIndexOf(" ");
        if (lastSpaceIndex == -1) {
            title = contentFormatLine;
            destPage = "1";
        } else {
            title = contentFormatLine.substring(0, lastSpaceIndex);
            destPage = contentFormatLine.substring(lastSpaceIndex + 1);
        }

        String[] titleSplit = title.split(" ");
        int dotCount = titleSplit[0].split("http://.").length - 1;

        bookmark.setLevel(dotCount);
        bookmark.setPage(destPage);
        bookmark.setTitle(title);
        return bookmark;
    }

    private void addFirstOutlineReservedPdf(
            List<HashMap<String, Object>> outlines, PdfReader reader) {
        PdfDictionary catalog = reader.getCatalog();
        PdfObject obj = PdfReader.getPdfObjectRelease(catalog
                .get(PdfName.OUTLINES));
        // 沒有書簽
        if (obj == null || !obj.isDictionary())
            return;
        PdfDictionary outlinesDictionary = (PdfDictionary) obj;
        // 得到第一個書簽
        PdfDictionary firstOutline = (PdfDictionary) PdfReader
                .getPdfObjectRelease(outlinesDictionary.get(PdfName.FIRST));

        PdfString titleObj = firstOutline.getAsString((PdfName.TITLE));
        String title = titleObj.toUnicodeString();

        PdfArray dest = firstOutline.getAsArray(PdfName.DEST);

        if (dest == null) {
            PdfDictionary action = (PdfDictionary) PdfReader
                    .getPdfObjectRelease(firstOutline.get(PdfName.A));
            if (action != null) {
                if (PdfName.GOTO.equals(PdfReader.getPdfObjectRelease(action
                        .get(PdfName.S)))) {
                    dest = (PdfArray) PdfReader.getPdfObjectRelease(action
                            .get(PdfName.D));
                }
            }
        }
        String destStr = parseDestString(dest, reader);

        String[] decodeStr = destStr.split(" ");
        int num = Integer.valueOf(decodeStr[0]);
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("Title", title);
        map.put("Action", "GoTo");
        map.put("Page", num + " Fit");

        outlines.add(map);
    }

    private String parseDestString(PdfArray dest, PdfReader reader) {
        String destStr = "";
        if (dest.isString()) {
            destStr = dest.toString();
        } else if (dest.isName()) {
            destStr = PdfName.decodeName(dest.toString());
        } else if (dest.isArray()) {
            IntHashtable pages = new IntHashtable();
            int numPages = reader.getNumberOfPages();
            for (int k = 1; k <= numPages; ++k) {
                pages.put(reader.getPageOrigRef(k).getNumber(), k);
                reader.releasePage(k);
            }

            destStr = makeBookmarkParam((PdfArray) dest, pages);
        }
        return destStr;
    }

    private String makeBookmarkParam(PdfArray dest, IntHashtable pages) {
        StringBuffer s = new StringBuffer();
        PdfObject obj = dest.getPdfObject(0);
        if (obj.isNumber()) {
            s.append(((PdfNumber) obj).intValue() + 1);
        } else {
            s.append(pages.get(getNumber((PdfIndirectReference) obj)));
        }
        s.append(' ').append(dest.getPdfObject(1).toString().substring(1));
        for (int k = 2; k < dest.size(); ++k) {
            s.append(' ').append(dest.getPdfObject(k).toString());
        }
        return s.toString();
    }

    private int getNumber(PdfIndirectReference indirect) {
        PdfDictionary pdfObj = (PdfDictionary) PdfReader
                .getPdfObjectRelease(indirect);
        if (pdfObj.contains(PdfName.TYPE)
                && pdfObj.get(PdfName.TYPE).equals(PdfName.PAGES)
                && pdfObj.contains(PdfName.KIDS)) {
            PdfArray kids = (PdfArray) pdfObj.get(PdfName.KIDS);
            indirect = (PdfIndirectReference) kids.getPdfObject(0);
        }
        return indirect.getNumber();
    }
}

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品国偷自产在线视频| 欧美日韩国产精品一区二区不卡中文| 5252色成人免费视频| 91人人爽人人爽人人精88v| 午夜精品视频网站| 国产精品久久久久久亚洲调教| 日韩国产高清视频在线| 日韩视频在线免费观看| 久久久亚洲国产天美传媒修理工| 日韩精品小视频| 欧美午夜电影在线| 色偷偷亚洲男人天堂| 91精品久久久久久久久不口人| 午夜精品久久久久久久99热| 国产精品2018| 日韩av色综合| 久久中国妇女中文字幕| 午夜精品一区二区三区在线视频| 中文字幕视频一区二区在线有码| 国产精品久久久久久av| 欧美另类69精品久久久久9999| 欧美激情亚洲综合一区| 国产成人av在线播放| 91精品国产九九九久久久亚洲| 欧美尺度大的性做爰视频| 欧美电影《睫毛膏》| 亚洲精品国精品久久99热一| 91亚洲精品在线观看| 日韩av综合网| 欧美三级免费观看| 久久久亚洲精选| 国产精品看片资源| 国产在线观看精品一区二区三区| 最近中文字幕2019免费| 成人网在线视频| 中文字幕亚洲天堂| 国产日产亚洲精品| 在线视频免费一区二区| 久久不射热爱视频精品| 亚洲深夜福利网站| 色偷偷88888欧美精品久久久| 亚洲欧美国产日韩中文字幕| 国内精品伊人久久| 亚洲精品久久久久久久久久久| 日韩经典中文字幕在线观看| 久久久精品欧美| 成人在线小视频| 亚洲欧美色图片| 91性高湖久久久久久久久_久久99| 2018国产精品视频| 一本大道香蕉久在线播放29| 久久免费国产精品1| 色综合伊人色综合网| 国产精品久久久久久一区二区| 亚洲级视频在线观看免费1级| 久久久精品美女| 久久影视电视剧免费网站清宫辞电视| 久久手机免费视频| 欧美日韩精品在线| 亚洲欧美激情精品一区二区| 久久亚洲一区二区三区四区五区高| 国产精品99久久久久久www| 亚洲a中文字幕| 国产精品一区二区三区免费视频| 国产精品一区二区3区| 久久在线免费观看视频| 国产精品自产拍在线观看中文| 久久99精品国产99久久6尤物| 91社影院在线观看| 日韩女优在线播放| 亚洲影院污污.| 日韩成人在线视频网站| 亚洲品质视频自拍网| 久久精品国产欧美激情| 在线播放国产一区二区三区| 日韩欧美极品在线观看| 欧美另类极品videosbest最新版本| 国产欧美在线观看| 欧美乱大交做爰xxxⅹ性3| 欧美色欧美亚洲高清在线视频| 欧美日韩一区二区免费在线观看| 69久久夜色精品国产69| 亚洲视频在线观看| 日本高清+成人网在线观看| 91网站免费看| 精品国产一区二区三区久久| 精品亚洲精品福利线在观看| 国产精品69久久久久| 色樱桃影院亚洲精品影院| 亚洲激情在线观看视频免费| 69av在线播放| 91久热免费在线视频| 欧美日韩国产综合视频在线观看中文| 欧美老少配视频| 欧美成人免费在线视频| 国产日韩av在线| 亚洲成人黄色在线| 一区二区三区四区精品| 国产精品福利在线观看| 美乳少妇欧美精品| 美女扒开尿口让男人操亚洲视频网站| 中文字幕亚洲综合| 日本精品视频在线| 热久久这里只有精品| 欧美成人午夜剧场免费观看| 亚洲人免费视频| 色偷偷av一区二区三区乱| 欧美日韩成人黄色| 日韩电影在线观看永久视频免费网站| 日本成人精品在线| 亚洲成人精品av| 91精品国产综合久久香蕉| 亚洲视频精品在线| 久久夜色精品国产亚洲aⅴ| 欧美高清视频在线观看| 伊人激情综合网| 美女久久久久久久久久久| 91tv亚洲精品香蕉国产一区7ujn| 在线看日韩av| 欧美激情精品久久久久久免费印度| 亚洲成人三级在线| 国产精品欧美亚洲777777| 亚洲乱码一区二区| 亚洲美女中文字幕| 欧美日韩中文字幕日韩欧美| 久久精品国产一区二区电影| 在线电影av不卡网址| 成人激情免费在线| 91精品啪在线观看麻豆免费| 久久久久久91| 国产精品欧美风情| 欲色天天网综合久久| 2023亚洲男人天堂| 久久综合国产精品台湾中文娱乐网| 91精品国产高清自在线| 国产精品第七影院| 国产激情久久久久| 亚洲奶大毛多的老太婆| 亚洲在线免费观看| 欧美一级电影免费在线观看| 国产一区二区精品丝袜| 欧美性生活大片免费观看网址| 68精品久久久久久欧美| 国产成人亚洲综合| 国产亚洲a∨片在线观看| 成人国内精品久久久久一区| 亚洲无限乱码一二三四麻| 成人网在线免费观看| 欧美高清性猛交| 国产成人精品免高潮费视频| 国产成人精品在线| 亚洲精品免费网站| 国产视频久久久| 九九精品在线视频| 91成人精品网站| 欧美视频免费在线观看| 国产精品国产三级国产专播精品人| 国产精品久久久久久久久久久久| 久热精品在线视频| 国语自产精品视频在线看一大j8| 国产一区二区在线播放| 在线播放日韩av| 国产精品自拍小视频| 影音先锋欧美在线资源|