如何将java项目从打包到转为exe文件,再到任意电脑可执行的应用程序(每一步都明确其正确性,请放心查阅)下半集

                               请根据实际情况跳转对应部分

      如果java -jar可以跑起来的话,那么就可以进行这一步了,如果跑不起来,看我上一篇文章,有解决方案。

如何将java项目从打包到转为exe文件,再到任意电脑可执行的应用程序(每一步都明确其正确性,请放心查阅)-优快云博客

二、将jar包转为exe

         下载软件:launch4j,免费。

1.把jar包和jdk,放到同一个文件夹,最好在桌面新建一个文件夹放进去。注意,这里网上很多教程都说应该放jre,包括软件上面也显示应该放jre,但是就我实际使用来说,放jre有可能跑起来会报错,众所周知jdk包含jre,所以放jdk理论上没问题.实际上我只放jre报错,放jdk就能跑了。

2.打开launch4j,接下来配置看图即可:

        2.1 除指出外,其他项都为默认,不用管。

        2.2  除指出外,其他项都为默认,不用管。

        2.3  除指出外,其他项都为默认,不用管。 

特别注意,有的人他的jdk里面没有jre,正常来说是这样的:

没有jre的话那就网上搜搜,怎么在jdk里面生成jre,教程一大堆。

        2.4 点左上角小齿轮,不要疑惑为什么左上角的绿三角是灰的,它的理解是:齿轮是生成exe,绿三角是测试运行,如果你的是GUI的话,你点完小齿轮就可以点绿三角测试了,Console不行,需要自己双击,如发生闪退,用cmd命令行运行即可。

        注意:点击小齿轮会弹出来一个保存文件选项,其实保存的是配置文件xml,你随便起个名就行,这是为了方便你以后可以从这个xml导入你刚刚做的配置。

        2.7看launch4j的下方的log是不是success,是的话桌面就会出现exe了,如下:

注意,此时还不能把exe发给电脑上没有java环境的用户,必须连同这个文件夹里面的jdk-17.0.1也打包过去,原因是:还记得我们配置jre的时候怎么配置的吗? ./jdk-17.0.1  也就是当前目录下的jre,你不把jdk-17.0.1也带过去的话,它./jdk-17.0.1 找不到了。

所以接下来就是要摆脱这个弊端了。

三、将exe变为任何电脑可运行的程序

        问:这一步在干什么事:

        答:把exe和所依赖的jdk一起给打包到一个应用程序安装器里面,最后只需要把这个安装包发给他人,其他人就可以根据安装包流程安装出exe和jdk了,比较高级。 

        1.下载Inno Setup 6,免费。

        2. 如下

        

       3.

         4.

        5. 

        6.

7.剩下一路next即可,最后会生成一个配置文件,你在左上角点那个蓝三角就可以运行生成了。最后会得到一个安装器,以后你把安装器发给任何人,它根据这个安装就可以把exe和jdk都一起安装好了,这也是一个成熟软件的样子。

                                                    好了,全部完成,从打包到发布。 

                                                          有问题可以在评论区提出。

# 题目重述 根据文档《实验6、《算法应用实验》.docx》内容,实验题目为: **哈夫曼编码压缩实验**——利用贪心思想实现 Huffman 编码,对文本文件进行压缩与解压缩,并统计压缩率与耗时性能。 --- # 给出答案(答案为带注释的代码块) ```java import java.io.*; import java.util.*; /** * 哈夫曼编码压缩与解压缩实现(适用于IntelliJ IDEA) */ public class HuffmanCompression { // 字符频率映射 private Map<Byte, Integer> frequencyMap = new HashMap<>(); // 哈夫曼编码表:字节 -> 二进制字符串 private Map<Byte, String> huffmanCodes = new HashMap<>(); // 哈夫曼树根节点 private HuffmanNode root; /** * 步骤1:读取文件并统计字符频率 */ public void buildFrequency(String filepath) throws IOException { try (FileInputStream fis = new FileInputStream(filepath)) { int data; while ((data = fis.read()) != -1) { byte b = (byte) data; frequencyMap.put(b, frequencyMap.getOrDefault(b, 0) + 1); } } } /** * 步骤2:构建哈夫曼树 */ public void buildHuffmanTree() { PriorityQueue<HuffmanNode> pq = new PriorityQueue<>(Comparator.comparingInt(n -> n.weight)); // 创建叶子节点加入优先队列 for (Map.Entry<Byte, Integer> entry : frequencyMap.entrySet()) { pq.offer(new HuffmanNode(entry.getKey(), entry.getValue())); } // 贪心合并最小权值节点 while (pq.size() > 1) { HuffmanNode left = pq.poll(); HuffmanNode right = pq.poll(); HuffmanNode parent = new HuffmanNode(null, left.weight + right.weight); parent.left = left; parent.right = right; pq.offer(parent); } root = pq.poll(); // 根节点 } /** * 步骤3:生成哈夫曼编码表 */ public void generateCodes() { if (root == null) return; StringBuilder code = new StringBuilder(); generateCodesHelper(root, code); } private void generateCodesHelper(HuffmanNode node, StringBuilder code) { if (node.data != null) { huffmanCodes.put(node.data, code.toString()); return; } if (node.left != null) { code.append('0'); generateCodesHelper(node.left, code); code.deleteCharAt(code.length() - 1); } if (node.right != null) { code.append('1'); generateCodesHelper(node.right, code); code.deleteCharAt(code.length() - 1); } } /** * 步骤4:压缩文件 */ public void compress(String inputPath, String outputPath) throws IOException { long startTime = System.currentTimeMillis(); try (FileInputStream fis = new FileInputStream(inputPath); FileOutputStream fos = new FileOutputStream(outputPath); ObjectOutputStream oos = new ObjectOutputStream(fos)) { // 写入哈夫曼编码表(用于解压) oos.writeObject(huffmanCodes); // 读取原文并生成比特流 ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); int data; while ((data = fis.read()) != -1) { byte b = (byte) data; String codeStr = huffmanCodes.get(b); for (char bit : codeStr.toCharArray()) { byteStream.write(bit == '1' ? 1 : 0); } } // 将比特流写入文件(字节对齐) byte[] bits = byteStream.toByteArray(); int padding = 8 - (bits.length % 8); if (padding != 8) { for (int i = 0; i < padding; i++) { byteStream.write(0); // 补0 } } byte[] paddedBits = byteStream.toByteArray(); ByteArrayOutputStream compressedBytes = new ByteArrayOutputStream(); for (int i = 0; i < paddedBits.length; i += 8) { byte b = 0; for (int j = 0; j < 8 && i + j < paddedBits.length; j++) { b |= (paddedBits[i + j] << (7 - j)); } compressedBytes.write(b); } oos.writeInt(padding); // 记录填充位数 oos.write(compressedBytes.toByteArray()); long endTime = System.currentTimeMillis(); System.out.println("压缩耗时: " + (endTime - startTime) + " ms"); System.out.println("原始大小: " + new File(inputPath).length() + " bytes"); System.out.println("压缩后大小: " + new File(outputPath).length() + " bytes"); double ratio = 100.0 * (1 - (double) new File(outputPath).length() / new File(inputPath).length()); System.out.printf("压缩率: %.2f%%\n", ratio); } } /** * 步骤5:解压缩文件 */ public void decompress(String compressedPath, String outputPath) throws IOException, ClassNotFoundException { long startTime = System.currentTimeMillis(); try (FileInputStream fis = new FileInputStream(compressedPath); ObjectInputStream ois = new ObjectInputStream(fis); FileOutputStream fos = new FileOutputStream(outputPath)) { @SuppressWarnings("unchecked") Map<Byte, String> codes = (Map<Byte, String>) ois.readObject(); int padding = ois.readInt(); // 反向映射:编码 -> 字符 Map<String, Byte> reverseCodes = new HashMap<>(); for (Map.Entry<Byte, String> entry : codes.entrySet()) { reverseCodes.put(entry.getValue(), entry.getKey()); } // 读取压缩数据转为比特流 byte[] compressedData = ois.readAllBytes(); StringBuilder bits = new StringBuilder(); for (byte b : compressedData) { for (int i = 7; i >= 0; i--) { bits.append((b >> i) & 1); } } // 移除填充位 if (padding > 0 && padding < 8) { bits.setLength(bits.length() - padding); } // 解码 StringBuilder currentCode = new StringBuilder(); for (int i = 0; i < bits.length(); i++) { currentCode.append(bits.charAt(i)); if (reverseCodes.containsKey(currentCode.toString())) { fos.write(reverseCodes.get(currentCode.toString())); currentCode.setLength(0); } } long endTime = System.currentTimeMillis(); System.out.println("解压耗时: " + (endTime - startTime) + " ms"); } } // 哈夫曼树节点 static class HuffmanNode { Byte data; int weight; HuffmanNode left, right; HuffmanNode(Byte data, int weight) { this.data = data; this.weight = weight; } } /** * 主函数测试 */ public static void main(String[] args) { HuffmanCompression hc = new HuffmanCompression(); String input = "input.txt"; // 输入文件路径 String compressed = "output.bin"; // 压缩文件路径 String decompressed = "decompressed.txt"; // 解压输出路径 try { hc.buildFrequency(input); hc.buildHuffmanTree(); hc.generateCodes(); hc.compress(input, compressed); hc.decompress(compressed, decompressed); } catch (Exception e) { e.printStackTrace(); } } } ``` --- # 代码解析 ### **操作步骤详解(在 IntelliJ IDEA 中执行)** #### ✅ 步骤 1:创建项目 1. 打开 **IntelliJ IDEA**。 2. 新建一个 Java 项目(如 `HuffmanExperiment`)。 3. 在 `src` 目录下新建类 `HuffmanCompression.java`。 #### ✅ 步骤 2:粘贴代码 - 将上述完整代码复制粘贴到 `HuffmanCompression.java` 文件中。 #### ✅ 步骤 3:准备测试文件 1. 在项目根目录或 `src` 同级目录下创建一个文本文件 `input.txt`。 2. 写入任意英文内容,例如: ``` This is a test file for Huffman compression. ``` #### ✅ 步骤 4:运行程序 1. 点击运行按钮或使用快捷键运行 `main` 方法。 2. 程序将自动生成: - `output.bin`:压缩后的二进制文件 - `decompressed.txt`:解压还原的文件 #### ✅ 步骤 5:查看结果 - 控制台会输出: - 压缩/解压耗时 - 原始大小 vs 压缩后大小 - 压缩率(例如:60.5%) - 比较 `input.txt` 和 `decompressed.txt` 内容是否一致 #### ✅ 注意事项 - 若出现文件找不到错误,检查文件路径是否正确(可改为绝对路径调试)。 - 使用 `ObjectOutputStream` 和 `ObjectInputStream` 保证对象序列化支持。 --- # 知识点(列出该代码中遇到的知识点) **1. 贪心算法(Huffman 编码构造)** 每次选频率最小两节点合并,局部最优导致全局最优,时间复杂度 $O(n \log n)$。 **2. 哈夫曼树与前缀编码** 无前缀性确保唯一可译;高频字符短码,低频长码,实现熵编码最优压缩。 **3. 位操作与字节对齐** 将比特流打包成字节需补位记录,读写时移位还原,避免数据错位丢失。
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值