EPBU/MOBI转PDF

news2024/11/17 21:51:46

--痛苦

--不爱BB 直接上码。 

 

写了一个java方法,转epub 或者mobi 为 pdf的方法 (单个转换)

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;

public class EbookConverter {

    public static void main(String[] args) {
        try {
            // 桌面路径
            String userHome = System.getProperty("user.home");
            String desktopPath = userHome + File.separator + "Desktop";

            // 输入文件名(包括扩展名)
            String inputFileName = "example.epub"; // 修改为实际文件名

            // 输入文件路径
            String inputFilePath = desktopPath + File.separator + inputFileName;

            // 输出文件路径(更改扩展名为 .pdf)
            String outputFileName = inputFileName.substring(0, inputFileName.lastIndexOf('.')) + ".pdf";
            String outputFilePath = desktopPath + File.separator + outputFileName;

            // 转换文件
            convertEbookToPdf(inputFilePath, outputFilePath);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void convertEbookToPdf(String inputFilePath, String outputFilePath) throws IOException, InterruptedException {
        // 判断文件格式
        String fileExtension = getFileExtension(inputFilePath).toLowerCase();

        if (!fileExtension.equals("epub") && !fileExtension.equals("mobi")) {
            throw new IllegalArgumentException("Unsupported file format. Only EPUB and MOBI are supported.");
        }

        // 使用 Calibre 的 ebook-convert 工具
        String command = String.format("ebook-convert \"%s\" \"%s\"", inputFilePath, outputFilePath);

        // 启动进程
        Process process = Runtime.getRuntime().exec(command);
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));

        // 记录开始时间
        long startTime = System.currentTimeMillis();

        // 读取输出并显示进度
        String line;
        while ((line = reader.readLine()) != null || (line = errorReader.readLine()) != null) {
            // 这里我们假设输出包含进度信息,可以根据具体的输出格式进行调整
            if (line.contains("%")) {
                System.out.println(line); // 打印带有百分比的行
            }
        }

        int exitCode = process.waitFor();

        // 记录结束时间
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;

        if (exitCode != 0) {
            throw new IOException("Error during conversion process. Exit code: " + exitCode);
        }

        System.out.println("Conversion successful: " + outputFilePath);
        System.out.println("Time taken: " + (duration / 1000) + " seconds");
    }

    private static String getFileExtension(String fileName) {
        int dotIndex = fileName.lastIndexOf('.');
        if (dotIndex > 0 && dotIndex < fileName.length() - 1) {
            return fileName.substring(dotIndex + 1);
        }
        return "";
    }
}

 

代码说明

  1. 启动进程:使用Runtime.getRuntime().exec(command)启动ebook-convert命令,并创建BufferedReader对象读取进程的标准输出和错误输出。
  2. 记录时间:在转换开始时记录开始时间,转换完成后记录结束时间,并计算耗时。
  3. 读取输出:在while循环中读取进程输出,并假设输出包含进度信息(例如百分比)。实际情况下,ebook-convert的输出格式需要根据具体情况调整解析方式。
  4. 显示进度:将包含百分比信息的行打印到控制台,模拟显示进度。
  5. 显示耗时:转换完成后,打印耗时信息。

注意事项

  • 进度信息ebook-convert工具的标准输出可能不包含详细的进度信息,需根据实际输出格式进行解析和调整。
  • 错误处理:在实际应用中,应增加更多的错误处理逻辑,例如捕获和处理可能的异常情况。
  • 优化:如果需要更详细和准确的进度更新,可以考虑使用支持更丰富反馈信息的转换工具或库。

 写了一个java方法,转epub 或者mobi 为 pdf的方法 (批量转换)

 以下是一个Java程序,用于批量将指定目录下的所有EPUB或MOBI文件转换为PDF文件,并将转换后的PDF文件保存到同一目录中,保持相同的文件名但后缀为PDF。

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

public class BatchEbookConverter {

    public static void main(String[] args) {
        // 指定要处理的目录路径
        String directoryPath = "C:\\Users\\Administrator\\Downloads\\pdf"; // 修改为实际目录路径

        File directory = new File(directoryPath);

        System.out.println("目录路径"+directoryPath);
        if (!directory.isDirectory()) {
            System.err.println("The provided path is not a directory.");
            System.exit(1);
        }

        File[] files = directory.listFiles((dir, name) -> name.toLowerCase().endsWith(".epub") || name.toLowerCase().endsWith(".mobi"));

        if (files == null || files.length == 0) {
            System.out.println("No EPUB or MOBI files found in the directory.");
            return;
        }

        for (File file : files) {
            String inputFilePath = file.getAbsolutePath();
            String outputFilePath = inputFilePath.substring(0, inputFilePath.lastIndexOf('.')) + ".pdf";

            try {
                convertEbookToPdf(inputFilePath, outputFilePath);
            } catch (IOException | InterruptedException e) {
                System.err.println("Failed to convert file: " + inputFilePath);
                e.printStackTrace();
            }
        }
    }

    public static void convertEbookToPdf(String inputFilePath, String outputFilePath) throws IOException, InterruptedException {
        // 判断文件格式
        String fileExtension = getFileExtension(inputFilePath).toLowerCase();

        if (!fileExtension.equals("epub") && !fileExtension.equals("mobi")) {
            throw new IllegalArgumentException("Unsupported file format. Only EPUB and MOBI are supported.");
        }

        // 使用 Calibre 的 ebook-convert 工具
        String command = String.format("ebook-convert \"%s\" \"%s\"", inputFilePath, outputFilePath);

        // 启动进程
        Process process = Runtime.getRuntime().exec(command);
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));

        // 记录开始时间
        long startTime = System.currentTimeMillis();

        // 读取输出并显示进度
        String line;
        while ((line = reader.readLine()) != null || (line = errorReader.readLine()) != null) {
            // 这里我们假设输出包含进度信息,可以根据具体的输出格式进行调整
            if (line.contains("%")) {
                System.out.println(line); // 打印带有百分比的行
            }
        }

        int exitCode = process.waitFor();

        // 记录结束时间
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;

        if (exitCode != 0) {
            throw new IOException("Error during conversion process. Exit code: " + exitCode);
        }

        System.out.println("Conversion successful: " + outputFilePath);
        System.out.println("Time taken: " + (duration / 1000) + " seconds");
    }

    private static String getFileExtension(String fileName) {
        int dotIndex = fileName.lastIndexOf('.');
        if (dotIndex > 0 && dotIndex < fileName.length() - 1) {
            return fileName.substring(dotIndex + 1);
        }
        return "";
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

23-LINUX--TCP连接状态

一.TCP服务的特点 传输层协议主要有两个&#xff1a;TCP 协议和 UDP协议。TCP 协议相对于UDP协议的特点是&#xff1a;面向连接、字节流和可靠传输。 使用TCP协议通信的双方必须先建立连接&#xff0c;然后才能开始数据的读写。双方都必须为该连接分配必要的内核资源&a…

VUE3+TS+elementplus创建table,纯前端的table

一、前言 开始学习前端&#xff0c;直接从VUE3开始&#xff0c;从简单的创建表格开始。因为自己不是专业的程序员&#xff0c;编程主要是为了辅助自己的工作&#xff0c;提高工作效率&#xff0c;VUE的基础知识并不牢固&#xff0c;主要是为了快速上手&#xff0c;能够做出一些…

141.字符串:重复的字符串(力扣)

题目描述 代码解决 class Solution { public:// 计算字符串s的next数组&#xff0c;用于KMP算法void getNext(int *next, const string& s){int j 0; // j是前缀的长度next[0] 0; // 初始化next数组&#xff0c;第一个字符的next值为0for (int i 1; i < s.size(); …

Colab/PyTorch - 006 Mask RCNN Instance Segmentation

Colab/PyTorch - 006 Mask RCNN Instance Segmentation 1. 源由2. 用 PyTorch 实现 Mask R-CNN2.1 输入输出2.2 预训练模型2.3 模型预测2.4 目标检测流程2.5 推理示例一示例二示例三 3. 推断时间比较(CPU v.s. GPU)4. 总结5. 参考资料 1. 源由 在《Colab/PyTorch - 004 Torchv…

css绘制下雨的云朵

效果&#xff1a; 具体实现&#xff1a; html <div class"wuyun"><div class"yun"><div class" yu yu1"></div><div class" yu yu2"></div><div class" yu yu3"></div>&…

UE5中搭建一个简单的海岛

本文将用UE的WaterSystem与地形搭建一个简单的海岛&#xff0c;通过WaterSystem的参数设置&#xff0c;可以更好的自定义海岸线等效果。 1.基础风貌 1.1.首先新建一个Basic基础场景&#xff0c;切换到地形编辑模式刷出一块高地&#xff0c;用于沙滩。 1.2.引入UE官方插件Wat…

【刷题(11)】栈

一、栈基础 &#xff08;1&#xff09;常用操作&#xff1a;push pop top &#xff08;2&#xff09;最小栈&#xff1a;最小栈也是一个栈(存的元素都是数字)&#xff0c;只不过这种数据结构除了有push、pop、top等和普通栈相同的方法外&#xff0c;还有一个方法get_min用来获…

利用Spring AOP与Python装饰器完成相同任务

文章目录 一、提出任务二、采用配置方式Spring AOP完成任务1. 项目结构2. 创建任务类SlayDragonQuest.javaRescueDamselQuest.java 3. 创建骑士类BraveKnight.javaRescueDamselKnight.java 4. 创建游吟诗人类Minstrel.java 5. 创建Spring配置文件spring-config.xml 6. 添加AOP相…

MySQL的备份及恢复

目录 5、MySQL的备份及恢复 5.1 MySQL日志管理 5.1.1 MySQL日志类型 5.1.2 错误日志 5.1.3 通用查询日志 5.1.4 慢查询日志 5.1.5 二进制日志 开启日志 二进制日志管理>又叫日志滚动 二进制日志还原数据 删除二进制日志文件&#xff1a; 5.1.6实例&#xff1a; 使用mysqlbi…

wordpress教程视频 wordpress教程网盘 wordpress教程推荐wordpress教程网

WordPress&#xff0c;作为一款强大且灵活的开源内容管理系统&#xff0c;已成为许多网站开发者与运营者的首选。其强大的功能、丰富的插件以及易于上手的特点&#xff0c;使得无论是初学者还是专业开发者都能轻松构建出个性化的网站。然而&#xff0c;对于初学者来说&#xff…

【LeetCode算法】第69题:x的平方根

目录 一、题目描述 二、初次解答 三、官方解法 四、总结 一、题目描述 二、初次解答 1. 思路&#xff1a;第一次想到的是让i从1开始遍历&#xff0c;看i*ix是否成立&#xff0c;但是这样就会导致i*i超出了int的范围&#xff0c;无法正常求解。第二次&#xff0c;想着比较x/…

Design-expert中的ANOVA分析

文章目录 1.ANOVA for Quadratic model部分2.Fit Statistics部分3.拟合方程含义 1.ANOVA for Quadratic model部分 在Design-Expert软件中&#xff0c;ANOVA&#xff08;Analysis of Variance&#xff09;用于评估模型中各个参数的显著性&#xff0c;特别是在处理二次模型&…

流媒体新篇章:Nginx-RTMP Docker部署全攻略

概述 Nginx-RTMP-Docker是一种基于Docker的Nginx流媒体服务器解决方案。具体来说&#xff0c;Nginx是一款高性能的Web和反向代理服务器&#xff0c;RTMP&#xff08;Real-Time Messaging Protocol&#xff09;是用于音频、视频数据传输的协议。Nginx-RTMP模块是由Alibaba的李广…

Redis离线安装(单机)

目录 1-环境准备1-1下载redis-4.0.11.tar.gz1-2gcc环境 2-上传解压3-编译安装(需要gcc环境)4-配置redis5-启动Redis6-开启防火墙(root)7-添加开机启动脚本8-设置权限9-设置开机启动10-测试redis服务11-检查是否安装成功12-创建redis命令软连接13-测试redis14-必要时设置防火墙 …

浅析declval关键字

浅析 declval 关键字 文章目录 浅析 declval 关键字前言declval 的基本概念declval 的工作原理declval 的实际应用案例总结 前言 ​ 在现代C编程中&#xff0c;std::declval是一个非常有用的工具&#xff0c;它允许我们在不实例化对象的情况下使用其类型。这在模板元编程中尤其…

OpenAI 与 Reddit 达成重要合作伙伴关系

Reddit是一个娱乐、社交及新闻网站&#xff0c;注册用户可以将文字或链接在网站上发布&#xff0c;使它基本上成为了一个电子布告栏系统。注册用户可以对这些帖子进行投票&#xff0c;结果将被用来进行排名和决定它在首页或子页的位置。网站上的内容分类被称为“subreddit”。s…

Vue3实战笔记(39)—封装页脚组件,附源码

文章目录 前言一、封装页脚组件二、使用组件总结 前言 在Web开发中&#xff0c;页脚组件是一个重要的部分&#xff0c;它为用户提供关于网站的信息、导航链接以及版权声明等。而封装页脚组件则是一种高效的方法&#xff0c;可以提高代码的可重用性和可维护性。 一、封装页脚组…

4.2 循环语句(for, while)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

高中数学:平面向量-正交分解、坐标表示、坐标运算

一、正交分解 二、坐标表示 这里注意一点 坐标A(x,y)与向量 a → \mathop{a}\limits ^{\rightarrow} a→的坐标记作&#xff1a; a → \mathop{a}\limits ^{\rightarrow} a→(x,y)&#xff0c;表示方式的区别 引申 三、加减运算的坐标表示 四、数乘运算的坐标表示 引申 两向量…

爬虫学习--12.MySQL数据库的基本操作(下)

MySQL查询数据 MySQL 数据库使用SQL SELECT语句来查询数据。 语法&#xff1a;在MySQL数据库中查询数据通用的 SELECT 语法 SELECT 字段1&#xff0c;字段2&#xff0c;……&#xff0c;字段n FROM table_name [WHERE 条件] [LIMIT N] 查询语句中你可以使用一个或者多个表&…