Unity-PDF分割器(iTextSharp)

PDF分割器

  • Unity-PDF分割器
    • 前言
    • 核心思路
    • 解决过程
      • 一、Unity安装iTextSharp
      • 二、运行时计算将要生成文件的大小
      • 三、分割核心代码
      • 四、使用StandaloneFileBrowser
      • 五、其他的一些脚本
      • 六、游戏界面主体的构建
        • MainWindow
        • WarningPanel & FinishPanel
  • By-Round Moon

Unity-PDF分割器

PDFSplitter 资源包下载链接【CSDN】免费

前言

最近有这么一个需求,PDF太大了,需要拆分成多份,要求每份的PDF不大于10MB。刚开始,我认为这应该很简单,但是足足耗费了一天的时间去解决该问题。

核心思路

首先是核心部分当然是PDF如何进行分割了,不仅仅要分割,还要统计分割的大小。然后我还不想伤硬盘,直接写在硬盘上判断文件是否超过了大小,然后回溯。所以我只能在运行的时候检测文件大小。核心部分的难度基本如上所述。下面来讲解一下我是如何解决这个问题的吧。还有一个最难的问题,那就是如何不用UnityEditor库来打开FilePanel又叫FileDialog

解决过程

一、Unity安装iTextSharp

在这里插入图片描述
    首先在Visual Studio Community中安装.NET 桌面开发,用来下载需要的dll。当然也可以直接在Unity中打开VS后下载,我这其实是脱裤子放屁,但是我想保持Unity的干净,不想事后卸载删除,所以我采用了这个方法。
    安装完成后创建一个控制台应用。在这里插入图片描述
将框架选为.NET Framework 2.0
打开后,在 工具》NuGet包管理器》管理解决方案的NuGet程序包。在浏览中搜索iTextSharp并安装。安装完成后,在.sln文件的同路径下有一个packages包,把里面BouncyCastle.1.8.9iTextSharp.5.5.13.3的lib文件夹下的.dll文件拷贝到Unity项目的Plugins(自己创建)文件夹中。
在这里插入图片描述

二、运行时计算将要生成文件的大小

    明确已知,没有提供方法来确定生成后的大小。但是我们可以先在MemoryStream中存储一下,并获取MemoryStream空间所消耗的大小。
    下面给出示例代码。

    long GetMemorySize(string inputFilePath)
    {
        PdfReader reader = new PdfReader(inputFilePath);
        Document document = new Document();
        MemoryStream memoryStream = new MemoryStream();
        PdfCopy copy = new PdfCopy(document, memoryStream);
        document.Open();
        copy.AddPage(copy.GetImportedPage(reader, 1));//这里页码是从1到最后的,不是常规的从0开始。
        long memorySize = memoryStream.Length;
        reader.Close();
        document.Close();
        memoryStream.Close();
        return memorySize;
    }

三、分割核心代码

这份脚本为PDFSplitter。将来挂在GameController空物体上。

using UnityEngine;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
using UnityEngine.UI;
using System.Collections.Concurrent;
using System.Collections;

public class PDFSplitter : MonoBehaviour
{
    private string inputFilePath;
    private string outputDirectory;
    private long maxFileSizeMB = 10 * 1024 * 1024;
    private PdfReader reader;
    public InputField from;
    public InputField save;
    public Slider slider;
    private ConcurrentQueue<float> resultQueue = new ConcurrentQueue<float>();
    public void Splitter()
    {
        System.Threading.Thread thread = new System.Threading.Thread(Run);
        thread.Start();
        StartCoroutine(updateSlider());
    }
    IEnumerator updateSlider()
    {
        float res;
        while (true)
        {
            while (!resultQueue.TryDequeue(out res)) ;
            if (res < 0)
            {
                slider.value = 1.0f;
                GetComponent<GameController>().showFinishPanel = true;
                break;
            }
            slider.value = res;
            yield return null;
        }
    }
    public void Run()
    {
        int cnt = 1;
        int pre = 1;
        float rate;
        inputFilePath = from.text;
        outputDirectory = save.text;
        reader = new PdfReader(inputFilePath);
        PdfReader.unethicalreading = true;
        Document document = null;
        MemoryStream memoryStream = null;
        PdfCopy copy = null;
        int pageCount = reader.NumberOfPages;
        for (int i = 1; i <= pageCount; i++)
        {
            if (document == null)
            {
                document = new Document();
                memoryStream = new MemoryStream();
                copy = new PdfCopy(document, memoryStream);
                document.Open();
                copy.AddPage(copy.GetImportedPage(reader, i));
            }
            else
            {
                copy.AddPage(copy.GetImportedPage(reader, i));
                if (memoryStream.Length > maxFileSizeMB)
                {
                    PDF_Writer(pre, i - 1, cnt++.ToString("00"));
                    document.Close();
                    memoryStream.Close();
                    document = null;
                    memoryStream = null;
                    copy = null;
                    pre = i--;
                }
            }
            rate = 1.0f * i / pageCount;
            resultQueue.Enqueue(rate);
        }
        document.Close();
        PDF_Writer(pre, pageCount, cnt.ToString("00"));
        reader.Close();
        resultQueue.Enqueue(-1.0f);
    }
    void PDF_Writer(int start, int end, string name)
    {
        Document document = new Document();
        PdfCopy copy = new PdfCopy(document, new FileStream(outputDirectory + $"//{name}.pdf", FileMode.Create));
        document.Open();
        for (int i = start; i <= end; i++)
            copy.AddPage(copy.GetImportedPage(reader, i));
        document.Close();
    }
}

四、使用StandaloneFileBrowser

首先在Github链接中下载StandaloneFileBrowser。
在这里插入图片描述
之后,就将下载的Packages直接拖进项目中导入。
用这个包之后为了能够打包成功我们需要将Unity的.Net框架改为 .Net 4.x在这里插入图片描述
    我们这里只需要使用StandaloneFileBrowser.OpenFilePanelStandaloneFileBrowser.OpenFolderPanel
可能导入时候会出一些莫名其妙的错误,不用在意,只要能编译正常用,打包正常打出去,就可以。奇怪的是打包成功之后这些错误莫名其妙的消失掉了。


这份脚本为PathBar。将来挂在涉及路径选择的自定义物体上。

using UnityEngine;
using UnityEngine.UI;
using SFB;

public class PathBar : MonoBehaviour
{
    [HideInInspector]
    public string path;
    public InputField info;

    public void SelectFilePath()
    {
        var extensions = new[] { new ExtensionFilter("PDF Files", "pdf"), new ExtensionFilter("All Files", "*") };
        path = StandaloneFileBrowser.OpenFilePanel("Open PDF File", "", extensions, false)[0];
        info.text = path;
    }
    public void SelectFolderPath()
    {
        path = StandaloneFileBrowser.OpenFolderPanel("Select save Folder", "", false)[0];
        info.text = path;
    }

}

五、其他的一些脚本

这份脚本为GameController 。将来挂在GameController空物体上。

using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using System.IO;
public class GameController : MonoBehaviour
{
    public GameObject FinishPanel;
    public GameObject WarningPanel;
    [HideInInspector]
    public bool showFinishPanel;
    public InputField from;
    public InputField save;
    public void Run()
    {
        if (!File.Exists(from.text) || !Directory.Exists(save.text) || Path.GetExtension(from.text).ToLower() != ".pdf")
        {
            WarningPanel.GetComponent<PanelController>().Open();
            return;
        }
        showFinishPanel = false;
        GetComponent<PDFSplitter>().Splitter();
        StartCoroutine(ShowFinishPanel());
    }
    IEnumerator ShowFinishPanel()
    {
        while (!showFinishPanel)
            yield return null;
        FinishPanel.GetComponent<PanelController>().Open();
    }
}

这份脚本为PanelController 。将来挂在一些用来提示的物体上。

using UnityEngine;

public class PanelController : MonoBehaviour
{
    public void Close()
    {
        gameObject.SetActive(false);
    }
    public void Open()
    {
        gameObject.SetActive(true);
    }
}

六、游戏界面主体的构建

MainWindow

在这里插入图片描述
界面如下,很好拆分上面的我称之为PathBar,用来选择路径。
中间是Button,用来执行分割操作。
最底下是进度条,可以参考B站视频 BV1iW411D78W大概在55分钟左右会有讲解。我这里多做了一步操作,把slider的图片全部设置成了None。
下面看一下我的目录结构
在这里插入图片描述

WarningPanel & FinishPanel

在这里插入图片描述
在这里插入图片描述
下面看一下我的目录结构
在这里插入图片描述
PDFSplitter 资源包下载链接【CSDN】免费

By-Round Moon

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/417628.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

浅谈 Linux 网络编程 socket

文章目录 socket 介绍 socket 介绍 socket 被翻译成 网络套接字&#xff0c;这个名字实在是不好理解&#xff0c;我更愿意称为"插槽"。 忽略 socket 的中文名&#xff0c;先无脑记住两个规则&#xff1a; ① 记住&#xff0c;一个文件描述符(fd) 指向一个 socket&…

同芯.共赢 | 暴雨服务器亮相AMD EPYC合作伙伴峰会

2月29日&#xff0c;AMD EPYC合作伙伴峰会活动在北京成功举行&#xff0c;暴雨作为AMD重要生态合作伙伴应邀参加。作为AMD开年首场活动&#xff0c;此次活动意义非凡&#xff0c;AMD在现场向合作伙伴分享了AMD数据中心全新产品路线、解决方案以及生态建设领域的最新进展。 AMD是…

android开发平台,Java+性能优化+APP开发+NDK+跨平台技术

开头 通常作为一个Android APP开发者&#xff0c;我们并不关心Android的源代码实现&#xff0c;不过随着Android开发者越来越多&#xff0c;企业在筛选Android程序员时越来越看中一个程序员对于Android底层的理解和思考&#xff0c;这里的底层主要就是Android Framewok中各个组…

机器学习专项课程03:Unsupervised Learning, Recommenders, Reinforcement Learning笔记 Week02

Week 02 of Unsupervised Learning, Recommenders, Reinforcement Learning 课程地址&#xff1a; https://www.coursera.org/learn/unsupervised-learning-recommenders-reinforcement-learning 本笔记包含字幕&#xff0c;quiz的答案以及作业的代码&#xff0c;仅供个人学习…

二分查找讲解

关于我为什么要写单独开一篇文章写二分,实际上那么多困难的算法,比如线段树,并查集等等都没有难倒我,我最近却被二分难倒了,而且是两次,两次在赛场上做不出来二分的应用题,于是我决定写一篇二分查找的算法总结.刚接触算法的时候本来是要写一篇的,但后面因为各种原因搁置了,现在…

R语言数学建模(二)—— tidymodels

R语言数学建模&#xff08;二&#xff09;—— tidymodels 文章目录 R语言数学建模&#xff08;二&#xff09;—— tidymodels前言一、示例数据集二、拆分数据集2.1 拆分数据集的常用方法2.2 验证集2.3 多层次数据2.4 其他需考虑问题 三、parsnip用于拟合模型3.1 创建模型3.2 …

腾讯云优惠券领取的三个渠道,先领券再下单!

腾讯云代金券领取渠道有哪些&#xff1f;腾讯云官网可以领取、官方媒体账号可以领取代金券、完成任务可以领取代金券&#xff0c;大家也可以在腾讯云百科蹲守代金券&#xff0c;因为腾讯云代金券领取渠道比较分散&#xff0c;腾讯云百科txybk.com专注汇总优惠代金券领取页面&am…

禁止safari浏览器网页双击缩放功能

普通浏览器 普通浏览器&#xff0c;只需要增加meta标签禁止缩放功能就行了 <meta content"widthdevice-width, initial-scale1.0, maximum-scale1.0, user-scalable0;" name"viewport" /> user-scalableno或0 //禁止双指缩放页面initial-scale1.0…

企业文件图纸加密有哪些?图纸文件加密防泄密软件如何选?

在现在的市场发展中&#xff0c;对于企业的图纸文件安全问题越来越重视&#xff0c;如设计图纸&#xff0c;重要文件等&#xff0c;一旦泄漏就会给企业造成巨大的经济损失。所以对企业管理者来讲&#xff0c;如何才能选择一款好用的适合本企业的图纸文件加密软件是非常重要的&a…

【C++】手把手教你手搓模拟实现string类

前言 string类一直都是C的经典问题&#xff0c;之前的文章已经对string类做了一个基本的介绍&#xff08;string类的基本常用接口&#xff09;&#xff0c;为了更好理解string类的功能&#xff0c;此篇文章将手把手教你带你手搓模拟实现string类&#xff0c;快来一起学习吧&am…

Spring 事务传播机制

事务传播机制&#xff1a;多个事务⽅法存在调⽤关系时, 事务是如何在这些⽅法间进⾏传播的。 ⽐如&#xff1a;有两个⽅法A&#xff0c;B都被 Transactional 修饰,&#xff0c;A⽅法调⽤B⽅法 A⽅法运⾏时, 会开启⼀个事务。当A调⽤B时&#xff0c; B⽅法本⾝也有事务&#xf…

Pod 进阶

目录 资源限制 健康检查 资源限制 当定义 Pod 时可以选择性地为每个容器设定所需要的资源数量。 最常见的可设定资源是 CPU 和内存大小&#xff0c;以及其他类型的资源。 当为 Pod 中的容器指定了 request 资源时&#xff0c;代表容器运行所需的最小资源量&#xff0c;调度器…

打造去中心化透明储蓄罐:Solidity智能合约的又一实践

一、案例背景 传统的储蓄罐通常是由个人或家庭使用&#xff0c;用于存放硬币或小额纸币。然而&#xff0c;这样的储蓄罐缺乏透明性&#xff0c;用户无法实时了解储蓄情况&#xff0c;也无法确保资金的安全性。 通过Solidity智能合约&#xff0c;我们可以构建一个去中心化…

外汇天眼:外汇市场有哪些功能?

外汇市场有三个方面的功能&#xff0c;一是实现购买力的国际转移&#xff0c;二是提供资金融通&#xff0c;三是提供外汇保值和投机的市场机制。 实现购买力的国际转移 国际贸易和国际资金融通至少涉及到两种货币&#xff0c;而不同的货币对不同的国家形成购买力&#xff0c;…

02| JVM堆中垃圾回收的大致过程

如果一直在创建对象&#xff0c;堆中年轻代中Eden区会逐渐放满&#xff0c;如果Eden放满&#xff0c;会触发minor GC回收&#xff0c;创建对象的时GC Roots&#xff0c;如果存在于里面的对象&#xff0c;则被视为非垃圾对象&#xff0c;不会被此次gc回收&#xff0c;就会被移入…

逆向案例一:AES解密基于数位观察城市数据

import requests import json from Crypto.Cipher import AES # 开始解密 from Crypto.Util.Padding import unpad #去填充的逻辑 import base64 url https://app.swguancha.com/client/v1/cPublic/consumer/baseInfo data {current: 1,"dimensionTime": "20…

数据结构--B树

B树的预备知识 我们平常查找比如用搜索二叉树哈希表这些数据结构&#xff0c;一般都是数据在内存中的&#xff0c;这样的话访问数据的速度就很快&#xff0c;这种查找也叫做内查找。二分查找或者直接顺序查找也适合内查找。 但是当数据量非常大时&#xff0c;比如有100G的数据…

redis启动错误

错误&#xff1a; Creating Server TCP listening socket 127.0.0.1:6379: bind: No error redis-server.exe redis.windows.conf redis-cli.exe shutdown auth "yourpassword"

【kubernetes】关于云原生之k8s集群中pod的容器资源限制和三种探针

目录 一、关于pod容器的资源限制 1.1资源限制的单位 CPU 资源单位 内存 资源单位 二、关于QOS服务质量&#xff08;pod的调度和驱逐有限制&#xff09; 2.1QoS服务质量分类 guaranteed验证 burstable验证 besteffort验证 2.2驱逐顺序 三、关于pod容器的三种探针 3.…

mobile app 安全扫描工具MobSF了解下

可以干啥&#xff1a; static 静态分析 dynamic 动态分析 可以用来渗透了 如何docker安装 docker image 下载地址https://hub.docker.com/r/opensecurity/mobile-security-framework-mobsf/ setup 两行即可 1 docker pull opensecurity/mobile-security-framework-mobsf…