一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專(zhuān)注于服務(wù)器技術(shù)及軟件下載分享
分類(lèi)導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務(wù)器之家 - 編程語(yǔ)言 - JAVA教程 - 使用java為pdf添加書(shū)簽的方法(pdf書(shū)簽制作)

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

2019-11-08 14:25java教程網(wǎng) JAVA教程

下載一些pdf格式的電子書(shū)沒(méi)有書(shū)簽,用JAVA寫(xiě)了一個(gè)小工具,將特定格式的文本解析成為書(shū)簽,然后保存到pdf格式中

由于我經(jīng)常下載一些pdf格式的電子書(shū),有的時(shí)候一些好書(shū)下載下來(lái)沒(méi)有書(shū)簽,讀起來(lái)感覺(jué)沒(méi)有整體的感覺(jué),所以決定自己寫(xiě)一個(gè)小工具,將特定格式的文本解析成為書(shū)簽,然后保存到pdf格式中。
整體思路是從豆瓣啊、京東啊、當(dāng)當(dāng)啊、亞馬遜下面的介紹中可以copy出目錄信息,拿《HTTP權(quán)威指南》為例:
目錄的結(jié)構(gòu)如:

復(fù)制代碼代碼如下:

第1章 HTTP 概述 3
1.1 HTTP——因特網(wǎng)的多媒體信使 4
1.2 Web 客戶(hù)端和服務(wù)器 4
1.3 資源 5
1.3.1 媒體類(lèi)型 6
1.3.2 URI 7
1.3.3 URL 7
1.3.4 URN 8
1.4 事務(wù) 9
1.4.1 方法 9
1.4.2 狀態(tài)碼 10
1.4.3 Web 頁(yè)面中可以包含多個(gè)對(duì)象 10
1.5 報(bào)文 11
1.6 連接 13

 

每一行后面都有頁(yè)碼,而且是用空格分開(kāi)的。
處理之后,結(jié)果為:
使用java為pdf添加書(shū)簽的方法(pdf書(shū)簽制作)

主要的邏輯為:

 

復(fù)制代碼代碼如下:


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, 那么是同一層的,這個(gè)時(shí)候,就加到ArrayList中,繼續(xù)往下面讀取
            if (level == preLevel) {
                outlines.add(map);
                addBookmarks(bufRead, outlines, map, level);
            }
            // 如果n>m,那么可以肯定,該行是上一行的孩子,, new 一個(gè)kids的arraylist,并且加入到這個(gè)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 , 那么就是說(shuō)孩子增加完了,退回到上層,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 = "";

        // 當(dāng)沒(méi)有頁(yè)碼在字符串結(jié)尾的時(shí)候,一般就是書(shū)的名字,如果格式正確的話(huà)。
        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("\\.").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));
        // 沒(méi)有書(shū)簽
        if (obj == null || !obj.isDictionary())
            return;
        PdfDictionary outlinesDictionary = (PdfDictionary) obj;
        // 得到第一個(gè)書(shū)簽
        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();
    }
}

 

 

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 韩国情事伦理片观看地址 | 免费观看网站 | 黑人巨大videosjapan高清 黑人好大 | 天堂一区二区在线观看 | 精品国产乱码久久久久久免费流畅 | 91制片厂(果冻传媒)原档破解 | 538精品视频 | 91麻豆精品国产自产在线观看 | 国产福利资源网在线观看 | 精品国产欧美一区二区三区成人 | 亚洲AV无码专区国产精品麻豆 | 男人的天堂在线观看免费 | 日韩在线二区 | 国产综合久久久久久 | 午夜在线观看免费完整直播网 | 欧美特一级 | 果冻传媒在线视频观看免费 | 91东航翘臀女神在线播放 | 成人精品视频一区二区在线 | 忘忧草在线社区WWW日本直播 | 国产精品调教 | 吉泽明步高清无码中文 | 奇米影视小说 | 欧洲另类一二三四区 | 国人精品视频在线观看 | 爱情岛论坛亚洲自拍 | 插入逼 | 茄子香蕉视频 | 色综合欧美色综合七久久 | 国产欧美一区二区三区精品 | 亚洲色图欧美视频 | 好大水好多好爽好硬好深视频 | 毛茸茸的大逼 | 91制片厂制作传媒网站破解 | 丰腴尤物贵妇浪荡小说 | 动漫精品午夜在线播放 | 天天综合天天影视色香欲俱全 | 美女脱了内裤打开腿让人桶网站o | 国产一区二区三区福利 | 不良网站在线观看 | 91在线亚洲综合在线 |