java IO创建HTML版PDF

本文介绍了一种将HTML文件转换为PDF文档的方法,包括处理不同类型的证书模板,支持多种语言和地区设置,以及如何通过Java和iText库实现这一过程。
public void viewPDF() {
    String tid = (String) getSessionAttr(SessionConstants.SELECTED_TENANT_ID);
    int personId = getSessionAttr(SessionConstants.USER_PERSON_ID_INT);
    Person applyPerson = PersonService.service.getPersonById(personId);
    String savePath = PropKit.get("uploadedFileSaveDirectory") + tid + File.separator + "sys" + File.separator;
    //String fileName = createPDF(applyPerson, tid);
   /* SysUploadFile suf = new SysUploadFile();
    suf.set("filename", "ABEC-IncomeCertificate.pdf");
    suf.set("savename", "");
    suf.set("filepath", savePath);
    suf.save();
    OnlineProof onlineProof = new OnlineProof();
    onlineProof.set("id", getPara("id"));
    onlineProof.set("upload_id", suf.get("id"));
    onlineProof.update();*/
    File htmlFile;
    File htmlMidFile = null;
    //FileReader reader = null;
    InputStreamReader reader = null;
    FileWriter writer = null;
    String url = this.getRequest().getServletContext().getRealPath("/");
    String proofType = getPara("proofType");
    String fileName = "";
    String country = getPara("country");
    String travelMode = getPara("travelMode");
    String fileUrl = url + "/resources/kong/";
    switch (proofType) {
        case "1":
            fileUrl += "Working Certificate.html";
            fileName += "Working Certificate";
            break;
        case "2":
            fileUrl += "Working and Income Certificate.html";
            fileName += "Working and Income Certificate";
            break;
        case "3":
            fileUrl += "Certificate for Loan.html";
            fileName += "Certificate for Loan";
            break;
        case "4":
            if ("1".equals(travelMode)) {
                if ("1".equals(country) || "2".equals(country) || "3".equals(country)
                        || "5".equals(country) || "6".equals(country) || "7".equals(country)) {
                    fileUrl += "Certificate for Visa - EU&Business.html";
                } else if ("8".equals(country)) {
                    fileUrl += "Certificate for Visa - UK&Business.html";
                } else if ("9".equals(country) || "10".equals(country) || "12".equals(country)) {
                    fileUrl += "Certificate for Visa - Asia&Business.html";
                } else if ("11".equals(country)) {
                    fileUrl += "Certificate for Visa - Taiwan&Businessl.html";
                }
            } else if ("2".equals(travelMode)) {
                if ("1".equals(country) || "2".equals(country) || "3".equals(country)
                        || "5".equals(country) || "6".equals(country) || "7".equals(country)) {
                    fileUrl += "Certificate for Visa - EU&Personal.html";
                } else if ("8".equals(country)) {
                    fileUrl += "Certificate for Visa - UK&Personal.html";
                } else if ("9".equals(country) || "10".equals(country) || "12".equals(country)) {
                    fileUrl += "Certificate for Visa - Asia&Personal.html";
                } else if ("11".equals(country)) {
                    fileUrl += "Certificate for Visa - Taiwan&Personal.html";
                }
            }
            fileName += "Certificate for Visa";
            break;
        case "5":
            fileUrl += "";
            fileName += "Certificate";
            break;
    }
    htmlFile = new File(fileUrl);// 指定要读取的文件

    try {

        reader = new InputStreamReader(new FileInputStream(htmlFile), "utf-8");
        //reader = new FileReader(htmlFile);
        // 获取该文件的输入流
        char[] bb = new char[1024];// 用来保存每次读取到的字符
        String str = "";// 用来将每次读取到的字符拼接,当然使用StringBuffer类更好
        int n;// 每次读取到的字符长度
        while ((n = reader.read(bb)) != -1) {
            str += (new String(bb, 0, n));
        }
        System.out.println(str);
        //替换HTML参数
        //str = str.replace("@Name_Cn@","test");

        htmlMidFile = new File(savePath + fileName+ ".html");// 要写入的文本文件

        if (!htmlMidFile.exists()) {// 如果文件不存在,则创建该文件
            htmlMidFile.createNewFile();
        }
        writer = new FileWriter(htmlMidFile);// 获取该文件的输出流
        writer.write(str);// 写内容
        writer.flush(); // 清空缓冲区,立即将输出流里的内容写到文件里
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (writer != null) {
            try {
                writer.close(); // 关闭输出流,施放资源
            } catch (IOException ignored) {
            }
        }
        if (reader != null) {
            try {
                reader.close(); // 关闭输入流,释放连接
            } catch (IOException ignored) {
            }
        }
    }
    //下载PDF文档
    Document document;
    // 将html转为pdf
    document = new Document(PageSize.A4, 36, 36, 108, 108);
    // 解决中文支持问题
    PdfWriter pdfwriter;
    try {
        pdfwriter = PdfWriter.getInstance(document, new FileOutputStream(savePath + fileName +  ".pdf"));
        document.open();
        String path = this.getRequest().getServletContext().getRealPath("/");
        Image img = Image.getInstance(path + "/img/ABEC.png");
        img.setAbsolutePosition(0, 0);
        img.scaleToFit(900, 860);
        document.add(img);
        //加载HTML
        XMLWorkerHelper.getInstance()
                .parseXHtml(
                        pdfwriter,
                        document,
                        new InputStreamReader(new FileInputStream(htmlFile), "utf-8"));
    } catch (DocumentException | IOException e) {
        e.printStackTrace();
    } finally {
        document.close();
        // 删除临时html
        htmlMidFile.delete();
    }
    //下载PDF
    try {
        FileOperateUtil.downloadx(getRequest(), getResponse(),
                savePath + fileName + ".pdf", "application/octet-stream",
                fileName + ".pdf");
    } catch (IOException e) {
        e.printStackTrace();
    }
}
【四轴飞行器】非线性三自由度四轴飞行器模拟器研究(Matlab代码实现)内容概要:本文围绕非线性三自由度四轴飞行器模拟器的研究展开,重点介绍了基于Matlab的建模与仿真方法。通过对四轴飞行器的动力学特性进行分析,构建了非线性状态空间模型,并实现了姿态与位置的动态模拟。研究涵盖了飞行器运动方程的建立、控制系统设计及数值仿真验证等环节,突出非线性系统的精确建模与仿真优势,有助于深入理解飞行器在复杂工况下的行为特征。此外,文中还提到了多种配套技术如PID控制、状态估计与路径规划等,展示了Matlab在航空航天仿真中的综合应用能力。; 适合人群:具备定自动控制理论基础和Matlab编程能力的高校学生、科研人员及从事无人机系统开发的工程技术人员,尤其适合研究生及以上层次的研究者。; 使用场景及目标:①用于四轴飞行器控制系统的设计与验证,支持算法快速原型开发;②作为教学工具帮助理解非线性动力学系统建模与仿真过程;③支撑科研项目中对飞行器姿态控制、轨迹跟踪等问题的深入研究; 阅读建议:建议读者结合文中提供的Matlab代码进行实践操作,重点关注动力学建模与控制模块的实现细节,同时可延伸学习文档中提及的PID控制、状态估计等相关技术内容,以全面提升系统仿真与分析能力。
我们来分析这个问题,并编写个符合要求的 Python 程序来判断小明是否能在有生之年(80年内)买得起房子。 --- ### 📌 问题解析 - 小明 **第一年年薪为 X 万元**,每年涨薪 **8%**(即乘以 1.08)。 - 房子初始价格为 **M 万元**,每年涨价 **10%**(即乘以 1.10)。 - 小明每年把全部工资存下来用于买房,所以: - 第1年结束时,他攒了第1年的工资; - 第2年结束时,他攒了前两年工资之和; - ... - 每年的累计存款 ≥ 当年房价 → 可以买房,输出是第几年(从第1年开始)。 - 最多计算到第 **80年**。如果超过80年才能买,输出 `Forget it.`。 --- ### ✅ 解题思路 使用循环逐年模拟: 1. 初始化: - 当前年薪 = X - 当前房价 = M - 总存款 = 0 2. 对每年(从第1年到第80年): - 把当年的工资加入总存款 - 判断当前总存款是否 ≥ 当年的房价? - 是:输出当前年份 N,结束 - 否则:年薪 *= 1.08,房价 *= 1.10,进入下年 3. 如果80年内都没买成,输出 `Forget it.` --- ### ✅ Python代码实现 ```python X = int(input()) M = int(input()) salary = X # 当前年薪 house_price = M # 当前房价 savings = 0 # 累计存款 for year in range(1, 81): # 从第1年到第80年 savings += salary # 年底拿到工资并存入 if savings >= house_price: print(year) break # 为下年做准备:涨薪和房价上涨 salary *= 1.08 house_price *= 1.10 else: # 循环正常结束,说明80年都没买得起 print("Forget it.") ``` --- ### 🔍 代码解释 - `for year in range(1, 81)`:控制最多计算80年。 - `savings += salary`:表示小明工作年后获得的总收入累计。 - `if savings >= house_price`:判断在第 `year` 年末是否有能力购买当前市场价格的房子。 - `salary *= 1.08` 和 `house_price *= 1.10`:按比例增长,注意是在判断之后更新下年的数据。 - 使用 `else` 子句配合 `for` 循环:只有当循环没有被 `break` 才执行,即80年都买不起。 --- ### ✅ 测试验证 #### 示例1: 输入: ``` 10 10 ``` 过程: - 第1年:工资=10,存款=10,房价=10 → 10>=10 → 成功!输出 `2`?等等! ⚠️ 注意:这里预期输出是 `2`,但看起来第1年就该买得起? 让我们仔细看逻辑。 实际上,题目隐含了个关键点: > **工资是年底发放,房价是年初报价还是年底?** 但从“第2年才买得起”来看,可能是这样理解的: - 第1年刚开始时,房价是 M - 小明要等到年底才能拿到工资 → 第1年结束时才有钱 - 此时房价已经涨了年? 但是根据我们的模型,我们在**当年末用当年工资 + 当年房价**比较。 那为什么 `X=10`, `M=10` 输出是 `2`? 说明可能:**房子是在年初涨价后再判断能否购买?或者工资还没发之前不能买?** 再重新审题:小明“攒够钱”,意味着他需要时间积累。 但如果是第一年: - 赚10万,攒10万 - 房价第一年是10万 → 应该能买 但预期输出是 `2`,这说明: ➡️ **很可能:房价在每年初上涨,工资在年末获得,因此第1年结束时,房价已经是 M×1.1,而存款是 X** 所以我们应该调整顺序: > 在第 `year` 年开始时,房价先涨(除了第1年),然后年底发工资、加存款、再判断? 不对,更合理的建模是: --- ### 🔄 修正模型(关键) | 时间线 | 事件 | |--------|------| | 第1年年初 | 房价 = M,小明开始工作 | | 第1年年末 | 小明拿到年薪 X,此时房价已涨到 M × 1.1?或仍是 M? | 但测试案例表明: - 输入:10 10 → 输出 2 说明:第1年结束时,小明攒了10万,但此时房价已经变成 10×1.1 = 11 > 10 → 买不起 - 第2年:工资涨为 10×1.08 = 10.8,总存款 = 10 + 10.8 = 20.8 - 房价变为 10×1.1^2 = 12.1 - 20.8 >= 12.1 → 第2年可以买 → 输出 2 ✅ 所以正确的逻辑是: > **每年初房价上涨(第1年除外),然后小明在年底获得工资并尝试购房** 或者等价地: - 第1年:房价 = M - 第2年起:房价每年乘1.1(先涨后判断) - 工资也是样:第1年是X,第2年才是X×1.08... 但要注意:工资是年薪,在年底才拿到! 所以正确的时间轴应为: ```text Year 1: - 开始:房价 = M - 结束:拿到工资 X,总存款 = X - 检查:X >= M? 否则继续 - 下年房价 = M * 1.1, 工资 = X * 1.08 Year 2: - 结束:再拿工资 (X*1.08),总存款 = X + X*1.08 - 当前房价 = M * 1.1 - 检查是否 >= - 更新:工资 *= 1.08, 房价 *= 1.1 ``` 也就是说: ✅ 在第 `i` 年末: - 小明的总存款 = X + X×1.08 + X×1.08² + ... + X×1.08^{i-1} - 房价 = M × 1.1^{i-1} ← 因为只涨了 i-1 次(第1年没涨) 因为: - 第1年:房价仍为 M = M × 1.1⁰ - 第2年:M × 1.1¹ - 第i年:M × 1.1^{i-1} 同理,第i年的工资是:X × 1.08^{i-1} 所以我们可以在循环中逐年累加。 --- ### ✅ 修改后的正确代码 ```python X = int(input()) M = int(input()) total_savings = 0 current_salary = X current_house_price = M for year in range(1, 81): total_savings += current_salary # 年底拿到工资 if total_savings >= current_house_price: print(year) break # 为下年准备:涨薪 & 房价上涨 current_salary *= 1.08 current_house_price *= 1.10 else: print("Forget it.") ``` --- ### ✅ 验证测试用例 #### 测试1: 输入: ``` 10 10 ``` 逐年计算: - Year 1: - 攒钱:10 → total = 10 - 房价:10 - 10 >= 10 → 成立 → 输出 1 ❌ 但预期是 2! 矛盾出现了! 但我们预期输出是 `2`,说明上面逻辑仍有误。 再查平台预期输出: > 输入:10 10 → 输出:2 说明即使第一年攒够了也不行? 难道意思是:**房价在每年初就上涨,包括第一年初?** 或者:**第一年结束后,房价立即上涨,然后再判断?** 换个角度思考: 也许题目中的“每年上涨10%”是指:**从第一年后开始涨价**,但在判断能否购买时,是基于涨价后的价格? 即: > 小明每年攒的钱只能用来买**涨价之后**的房子? 但逻辑上应该是:他在某年末有钱了,去看房,发现价格已经涨了。 所以我们应该认为: - 第1年结束时,房价已经涨为 M × 1.1 - 第2年结束时,房价是 M × 1.1² - ... - 第n年结束时,房价是 M × 1.1^n 而小明第n年结束时的存款是: > sum_{k=0}^{n-1} X × 1.08^k 工资是:第1年拿 X,第2年拿 X×1.08,...,第n年拿 X×1.08^{n-1} 所以总存款是等比数列求和。 同时,第n年结束时,房价已经经历了n次上涨?还是n-1次? 如果第一年结束就涨次,则第n年结束时涨了n次。 但原始房价是M,第1年结束 → M×1.1,第2年→ M×1.1² 所以: - 第n年结束时,房价 = M × (1.1)^n - 存款 = X × [1 + 1.08 + 1.08² + ... + 1.08^{n-1}] = X × (1.08^n - 1) / (0.08) 试试这个模型。 --- ### 再试测试1:X=10, M=10 找最小的 n ∈ [1,80] 使得: > 10 × (1.08^n - 1)/0.08 >= 10 × (1.1)^n ? No,不对,左边是存款总额,右边是房价。 但房价不是复利增长用于交易吗?是的。 但注意:存款是历年工资之和,而每年工资不同。 我们写个程序精确模拟: ```python X = int(input()) M = int(input()) savings = 0 salary = X house_price = M for year in range(1, 81): savings += salary # 判断在第 'year' 年末 是否买得起 当前价格的房子? # 但注意:这年结束时,房价是否已经上涨? # 如果房价是在每年末上涨,那么在上涨前还能按原价买? # 更合理假设:在每年末,先看能不能买,再决定涨不涨价? # 不对,应该是:到了年末,市场价已经涨了 → 你面对的是新价格 ``` 关键:**什么时候涨价?** 从测试数据反推: 输入:10 10 → 输出:2 说明第1年买不起。 即:第1年结束时,虽然有10万存款,但房价已经是 10×1.1 = 11 > 10 → 买不起 第2年: - 工资 = 10 × 1.08 = 10.8 - 存款 = 10 + 10.8 = 20.8 - 房价 = 10 × 1.1^2 = 12.1 - 20.8 >= 12.1 → 可以买 → 输出 2 ✅ 所以结论是: > **每年末,房价已经上涨了,小明拿着工资去买房,面对的是上涨后的价格** 但工资呢?第1年是X,第2年才是X×1.08? 是的。 所以时间线如下: ```text Year 1: - 年初:无事 - 年末:拿到年薪 X,同时房价已涨为 M * 1.1^1 - 检查:X >= M * 1.1 ? Year 2: - 年末:再拿工资 X * 1.08,总存款 = X + X*1.08 - 此时房价 = M * 1.1^2 - 检查是否 >= ``` 不对!工资是年薪,在年底发放,但涨幅是“每年涨薪8%”,意思是第二年才涨。 所以: - 第1年:工资 = X - 第2年:工资 = X * 1.08 - 第3年:X * 1.08^2 - ... 而房价: - 第1年末:M * 1.1 - 第2年末:M * 1.1^2 - ... 存款: - 第1年末:X - 第2年末:X + X*1.08 - 第3年末:X + X*1.08 + X*1.08^2 所以我们修改代码为: ```python X = int(input()) M = int(input()) total_savings = 0 current_salary = X for year in range(1, 81): total_savings += current_salary current_house_price = M * (1.10 ** year) # 第year年末,已涨year次 if total_savings >= current_house_price: print(year) break current_salary *= 1.08 else: print("Forget it.") ``` --- ### ✅ 验证测试1: X=10, M=10 | year | salary added | total_savings | house_price = M×1.1^year | 可买? | |------|---------------|----------------|----------------------------|--------| | 1 | 10 | 10 | 10×1.1 = 11 | 10 < 11 → 否 | | 2 | 10.8 | 20.8 | 10×1.21 = 12.1 | 20.8 >= 12.1 → 是 → 输出 2 ✅ | 完美匹配! ### 测试2: X=15, M=100 计算: - year1: - saving = 15 - house = 100 * 1.1 = 110 → 15 < 110 - next salary = 15 * 1.08 = 16.2 - year2: - saving = 15 + 16.2 = 31.2 - house = 100 * 1.1^2 = 121 → no - salary = 16.2 * 1.08 = 17.496 - year3: - saving = 31.2 + 17.496 = 48.696 - house = 133.1 → no 继续模拟直到满足条件。 我们可以运行代码验证。 --- ### ✅ 最终正确代码 ```python X = int(input()) M = int(input()) total_savings = 0 current_salary = X for year in range(1, 81): total_savings += current_salary current_house_price = M * (1.10 ** year) if total_savings >= current_house_price: print(year) break current_salary *= 1.08 else: print("Forget it.") ``` --- ### ✅ 代码解释 - `total_savings`:逐年累加工资收入。 - `current_salary`:表示第 `year` 年的年薪,第1年是X,之后每年×1.08。 - `current_house_price = M * (1.10 ** year)`:第 `year` 年末,房价已经上涨 `year` 次。 - 循环从1到80,旦满足条件就输出年份并退出。 - 否则输出 `Forget it.` --- ### ✅ 相关知识点 - 等比数列模拟 - 复利增长 - 年度财务模型设计 - 浮点数精度(本题无需担心,数据规模小) ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柠檬不萌c

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值