PDF文档繁体转换简体并支持复制

因为工作需要阅读一些繁体文档,例如香港IPO招股书等等,一个是大量阅读繁字体效率低,第二复制起来不方便。目前将繁字体转换为简体通常需要使用word文档,但PDF转word文档时间长、且一般是付费功能。这里想着用Java代码来实现这一转换操作。

1. maven依赖

        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.24</version>
        </dependency>

        <!-- 简体繁体转换 -->
        <!-- https://mvnrepository.com/artifact/com.github.houbb/opencc4j -->
        <dependency>
            <groupId>com.github.houbb</groupId>
            <artifactId>opencc4j</artifactId>
            <version>1.8.1</version>
        </dependency>

先用pdfbox来读取pdf文档,并用opencc4j来做简繁体转换。

2. 核心代码

使用的java版本是jdk21,可以根据需要自行转换为对应的java版本语法

    @Override
    @SneakyThrows
    public void simplify(InputStream is, OutputStream os) {
        try (PDDocument pd = PDDocument.load(is)) {
            // 需要的字体文件
            COSName fontName = null;
            PDFont targetFont = PDType0Font.load(pd, new FileInputStream("C:\\Windows\\Fonts\\STSONG.TTF"), false);
            int fontId = 0;
            for (PDPage page : pd.getPages()) {
                PDFStreamParser parser = new PDFStreamParser(page);
                COSName targetCosName = page.getResources().add(targetFont);
                parser.parse();
                List<Object> tokens = parser.getTokens();
                Map<COSName, PDFont> fontMap = new HashMap<>();
                for (COSName name : page.getResources().getFontNames()) {
                    PDFont font = page.getResources().getFont(name);
                    fontMap.put(name, font);
                }
                for (int j = 0; j < tokens.size(); j++) {
                    //创建一个object对象去接收标记
                    Object next = tokens.get(j);
                    //instanceof判断其左边对象是否为其右边类的实例
                    if (next instanceof COSName nextFont) {
                        fontId = j;
                        fontName = nextFont;
                        fontMap.put(fontName, page.getResources().getFont(fontName));
                    } else if (next instanceof COSString previous) {
                        if (fontMap.get(fontName) == null) {
                            continue;
                        }
                        try (InputStream in = new ByteArrayInputStream(previous.getBytes())) {
                            StringBuilder sb = new StringBuilder();
                            while (in.available() > 0) {
                                int rc = fontMap.get(fontName).readCode(in);
                                sb.append(fontMap.get(fontName).toUnicode(rc));
                            }
                            //重置COSString对象
                            String text = sb.toString();
                            String simplified = ZhConverterUtil.toSimple(text);
                            try {
                                previous.setValue(targetFont.encode(simplified));
                                tokens.set(fontId, targetCosName);
                            } catch (Exception e) {
                                log.error("", e);
                            }
                        }
                    } else if (next instanceof COSArray previous) {
                        //PDF中的字符串
                        byte[] pstring = {};
                        int prej = 0;
                        //循环previous
                        for (int k = 0; k < previous.size(); k++) {
                            Object arrElement = previous.getObject(k);
                            if (arrElement instanceof COSString cosString) {
                                //COSString对象>>创建java字符串的一个新的文本字符串。
                                //将此字符串的内容作为PDF文本字符串返回。
                                if (j == prej) {
                                    byte[] thisbyte = cosString.getBytes();
                                    byte[] temp = new byte[pstring.length + thisbyte.length];
                                    System.arraycopy(pstring, 0, temp, 0, pstring.length);
                                    System.arraycopy(thisbyte, 0, temp, pstring.length, thisbyte.length);
                                    pstring = temp;
                                } else {
                                    prej = j;
                                    pstring = cosString.getBytes();
                                }
                            }
                        }
                        if (fontMap.get(fontName) == null) {
                            continue;
                        }
                        try (InputStream in = new ByteArrayInputStream(pstring)) {
                            StringBuilder sb = new StringBuilder();
                            while (in.available() > 0) {
                                int rc = fontMap.get(fontName).readCode(in);
                                sb.append(fontMap.get(fontName).toUnicode(rc));
                            }
                            String text = sb.toString();
                            String simplified = ZhConverterUtil.toSimple(text);
                            try {
                                COSString cosString = (COSString) previous.getObject(0);
                                cosString.setValue(targetFont.encode(simplified));
                                tokens.set(fontId, targetCosName);
                            } catch (Exception e) {
                                log.error("", e);
                            }
                        }
                        int total = previous.size() - 1;
                        for (int k = total; k > 0; k--) {
                            previous.remove(k);
                        }
                    }
                }
                PDStream updatedStream = new PDStream(pd);
                OutputStream out = updatedStream.createOutputStream();
                ContentStreamWriter tokenWriter = new ContentStreamWriter(out);
                tokenWriter.writeTokens(tokens);
                page.setContents(updatedStream);
                out.close();
            }
            pd.save(os);
        }
    }

上面是参考了一些网上流传的代码,经过个人调试以后解决了繁体字体匹配简体字体,第二是加载字体时候要注意参数,否则字体没有嵌入(embedded)文档中,导致使用pdf阅读工具复制出来时乱码。

PDFont targetFont = PDType0Font.load(pd, new FileInputStream("C:\\Windows\\Fonts\\STSONG.TTF"), false);

另外就是pdfbox只能加载后缀为ttf的字体,需要注意。

转换前效果

转换后效果

 

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
批量正体简体转换chsToCht.bat 1.实现批量TXT文件正体转换简体。 2.实现批量TXT文件简体转换成正体。 3.文件名是简体,但内容是正体,则自动重命名为正体加.cht。 4.文件名是正体,但内容是简体,则自动重命名为简体加.chs。 5.选择转换后是否覆盖原文件。 6.指定转换后的文件存放目录。 7.在指定的目录上级生成日志文件。 批量PDF文件转换为TXT PdfToTxt.bat 1.批量把PDF文件中文字提取到对应的txt文件中。 2.指定转换后的文件存放目录。 3.在指定的目录上级生成日志文件。 批量Word文件转换为TXT WordToTxt.bat 1.批量把Word文件(.doc/.docx)中文字提取到对应的txt文件中。 2.指定转换后的文件存放目录。 3.在指定的目录上级生成日志文件。 批量复制所有的正体文件CopyChtTxt.bat 1.批量把所有文件名以.cht.txt结尾的文件全部提取到指定的目录中。 2.在指定的目录上级生成日志文件。 批量去除空格DleteSpace.bat 1.批量去除TXT文件中隔一个字一个空格的情况。 2.在指定的目录上级生成日志文件。 批量去掉TXT文件名中的非法字符RenameFile.bat 1.批量重命名文件,去除文件名中不规范的字符。 2.在指定的目录上级生成日志文件。 批量以TXT文件的第一行为文件名并去掉非法字符RenameFileFromFile.bat 1.批量以TXT文件内容第一行文件名,并去掉不规范字符为。 2.在指定的目录上级生成日志文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值