JavaFx学习问题3---Jar包路径问题 (疑难杂症)

  

文章目录

    • 前置提要:
    • 解决方法:
    • 调试JAR包
    • 后续补充:

前置提要:

  我做了的JavaFx程序中,需要通过一个文件夹的相对路径,获取文件夹下所有音频文件的路径,把这些路径字符串放到一个List集合里,然后用Media让它播放声音。问题就出在这个文件夹路径和音频文件路径在Java程序和Jar解析有区别

解决方法:

  通过文件夹相对路径获取文件夹下媒体文件的路径
  以下代码,在idea运行是没有问题的,其中floderPath是文件夹相对路径(/xxx/xxx的形式)

try {
     // 获取资源文件夹的URL
      URL folderUrl = getClass().getResource(folderPath);

     // 使用URL创建URI,并通过URI创建Path
     Path paths= Paths.get(URI.create(folderUrl.toString()));

     // 使用Files.newDirectoryStream遍历文件夹中的文件
    try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(paths)) {
          for (Path path : directoryStream) {
              if (Files.isRegularFile(path)) {
                 filePaths.add(path.toString());
              }
                        }
                    }
                } catch (IOException e) {
                    System.out.println("在本地读取文件时发生错误:" + e.getMessage());
}

  我打包成jar包,没多想就打成exe文件了,运行exe文件的时候点击按钮发生了错误。发生错误的话,他默认会在exe同级文件夹中生成一个errorLog.txt文件(我用的是exe4j打包的,其他打包工具我不知道会怎么样)。打开文件我发现p被解析成下图这样了,多了个jar
在这里插入图片描述
  于是我用String里的substring方法,把jar:去掉或者把jar:file:/去掉,发现DirectoryStream<> directoryStream = Files.newDirectoryStream(paths)得到的directoryStream 里面的路径也是错的。

原理:

(看个大概就行)
  当Java程序在本地运行时,相对路径是相对于当前工作目录解析的。当前工作目录是指在命令行或者IDE中执行Java程序的目录。例如,如果你的Java程序文件位于/home/user/program/Main.java,而你在/home/user/目录下执行Java程序,那么相对路径resources/file.txt将被解析为/home/user/resources/file.txt。

  然而,当Java程序被打包成JAR包后运行,相对路径是相对于类路径(Classpath)。JAR包是一种压缩文件格式,它将Java程序的所有类文件和资源文件打包在一起。当Java程序在JAR包中运行时,相对路径是相对于JAR包本身解析的。

  在JAR包中,路径前面会多出来jar:的部分,这是因为Java使用jar:作为URL协议来表示JAR包中的资源。例如,如果你的JAR包文件位于/home/user/program.jar,而其中的资源文件file.txt位于JAR包的根目录下,那么相对路径file.txt将被解析为jar:/home/user/program.jar!/file.txt。这种格式的路径称为"JAR URL"。

可以改成以下这样,去判断运行环境(我不知道其他方法,这应该是比较笨的方法了)

 try {
                    // 获取资源文件夹的URL
                    URL folderUrl = getClass().getResource(folderPath);

                    if (folderUrl != null) {
                        Path p;
                        if (folderUrl.toString().startsWith("jar:")) {
                            // 如果是在JAR中运行,使用以下方式获取路径
                            FileSystem fileSystem = FileSystems.newFileSystem(URI.create(folderUrl.toString()), Collections.emptyMap());
                            p = fileSystem.getPath(folderPath);
                            System.out.println(p);
                        } else {
                            // 如果在IDE中运行,使用以下方式获取路径
                            p = Paths.get(URI.create(folderUrl.toString()));
                        }

                        // 使用Files.newDirectoryStream遍历文件夹中的文件
                        try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(p)) {
                            for (Path path : directoryStream) {
                                if (Files.isRegularFile(path)) {
                                    System.out.println("音頻----"+path);
                                    filePaths.add(path.toString());
                                }
                            }
                        }
                    } else {
                        System.out.println("资源文件夹不存在");
                    }
                } catch (IOException e) {
                    System.out.println("在读取文件时发生错误:" + e.getMessage());
                }

  
获取完文件夹下的媒体文件路径,还要把他在项目中的相对路径转化上URI让Media去播放它
有以下两种转化方式,这里同样要去区别本地Java程序和Jar包环境

  getClass().getResource("/xxx/xxx").toURI() 括号里面为相对路径
  这种方式是通过类加载器(ClassLoader)获取资源的,适用于资源在类路径下的情况。在JAR包中,资源路径以 “jar:” 开头,表示这是一个JAR URL。适用于打包成JAR的情况。
例子:getClass().getResource(“/audio/sample.wav”).toURI()

&emsp;&emsp;Paths.get(audioFilePath).toUri():

  这种方式是通过文件系统路径获取资源的,适用于本地文件系统中的资源。如果你的资源是本地文件系统中的,而不是在JAR包中,可以使用这种方式。
例子:Paths.get(“C:/path/to/audio/sample.wav”).toUri()

  我是两个都用,因为jar包解析出来的路径会有 jar: 的前缀,通过判断是否有jar:就知道运行环境是哪个,然后用if去区别执行。

/**
     * 获取音频文件相对路径
     * @param audioFilePath
     * @param uri
     * @return
     * @throws URISyntaxException
     */
    public Media mediaUri(String audioFilePath,String uri) throws URISyntaxException {
        Media media;
        URI audioUri;
        System.out.println(audioFilePath);
        if (uri.startsWith("jar:")) {
            // 获取音频文件的URI,JAR环境
            audioUri = getClass().getResource(audioFilePath).toURI();
            media = new Media(audioUri.toString());
        }else {
            // 本地Java环境
            audioUri = Paths.get(audioFilePath).toUri();
            media=new Media(audioUri.toString());
        }
        return media;
    }

  

调试JAR包

在打包成exe文件前,建议先调试jar包。网上确实有些工具是可以调试exe文件的,但不咋方便,最好还是调试Java包。在终端输入 java -jar jar路径即可启动程序,代码里面写的System.out.println(),可以在终端打印出来。
在这里插入图片描述

后续补充:

  后面在运行jar包是发现FileSystem fileSystem = FileSystems.newFileSystem(URI.create(folderUrl.toString()), Collections.emptyMap());是会去创建uri的,如果一开始就有这个uri,那么会导致重复而创建失败,修改成下面代码就可以完美解决

try {
                    // 获取资源文件夹的URL
                    URL folderUrl = getClass().getResource(folderPath);

                    if (folderUrl != null) {
                        Path p;
                        if (folderUrl.toString().startsWith("jar:")) {
                            // 如果是在JAR中运行,使用以下方式获取路径
                            try {
                                FileSystem fileSystem = FileSystems.getFileSystem(URI.create(folderUrl.toString()));
                                p = fileSystem.getPath(folderPath);
                            } catch (FileSystemNotFoundException e) {
                                // 如果FileSystem不存在,则创建新的FileSystem
                                FileSystem fileSystem = FileSystems.newFileSystem(URI.create(folderUrl.toString()), Collections.emptyMap());
                                p = fileSystem.getPath(folderPath);
                            }
                        } else {
                            // 如果在IDE中运行,使用以下方式获取路径
                            p = Paths.get(URI.create(folderUrl.toString()));
                        }

                        // 使用Files.newDirectoryStream遍历文件夹中的文件
                        try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(p)) {
                            for (Path path : directoryStream) {
                                if (Files.isRegularFile(path)) {
                                    System.out.println("音頻----"+path);
                                    filePaths.add(path.toString());
                                }
                            }
                        }
                    } else {
                        System.out.println("资源文件夹不存在");
                    }
                } catch (IOException e) {
                    System.out.println("在读取文件时发生错误:" + e.getMessage());
                }

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

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

相关文章

周报6_YMK

周报6 本周主要在看代码&#xff1a;看Medusa头的代码发现不是很了解base_model那部分&#xff0c;所以又去看了llama2的代码和一些相关博客。 重写了一部分佛山中医学院项目的代码&#xff0c;更规范一些。 调研CosmoFlow&#xff0c;是一个深度学习预测宇宙参数的模型&…

git中的分支管理:git branch,git checkout,解决git中的分支冲突的方法【Git学习三】

&#x1f601; 作者简介&#xff1a;一名大四的学生&#xff0c;致力学习前端开发技术 ⭐️个人主页&#xff1a;夜宵饽饽的主页 ❔ 系列专栏&#xff1a;Git等软件工具技术的使用 &#x1f450;学习格言&#xff1a;成功不是终点&#xff0c;失败也并非末日&#xff0c;最重要…

【亚太杯思路助攻】2023年第十三届APMCM亚太地区大学生数学建模竞赛——(文末领取方式)

2023年第十三届APMCM亚太地区大学生数学建模竞赛——来啦&#xff01;&#xff01;&#xff01; 大家准备好了吗&#xff1f;别担心&#xff0c;【数模加油站】会像数模国赛、研赛一样&#xff0c;第一时间提供无偿解题思路、代码、参考文献等资料帮助大家。 祝各位小伙伴都能…

Instant Web API .Net Core Crack

Instant Web API .Net Core 是立即构建即时数据库 Web API&#xff0c;无需编码。在几分钟内生成您的 Web API&#xff0c;以更快地构建应用程序。使用 VS 2022 和 Entity Framework Core 为任何 MS SQL 数据库生成 Web API。 新功能 - 使用 Visual Studio 2022 为 PostgreSQL …

RTS 客户端-服务器网络

Stone Monarch 从一开始就支持多人游戏&#xff0c;但随着时间的推移&#xff0c;网络模型经历了多次迭代。我最初基于这篇著名的帝国时代文章实现了点对点锁步模型。 点对点锁定步骤有一些众所周知的问题。点对点方面使玩家很难相互连接&#xff0c;并增加了每个新玩家的网络…

【2018年数据结构真题】

方法一 给定一个含n(n>1)个整数的数组&#xff0c;请设计一个在时间上尽可能高效的算法&#xff0c;找出数组中未出现的最小正整数。例如&#xff0c;数组{-5&#xff0c;3&#xff0c;2&#xff0c;3}中未出现的最小正整数是1&#xff1b;数组{1&#xff0c;2&#xff0c;…

设计循环队列(详解)

呀哈喽&#xff0c;我是结衣 今天给大家带来的内容如标题所述&#xff0c;我们来设计环形队列&#xff0c;虽然队列没有讲&#xff0c;但是我就是想讲啊。那么环形队列现在开始。 队列的属性 在设计环形队列前&#xff0c;我们先要了解队列的特点&#xff08;先进先出&#x…

TypeScript枚举

1、数字枚举 enum Direction {Up,Down,Left,Right, } var Direction; (function (Direction) {Direction[Direction["Up"] 0] "Up";Direction[Direction["Down"] 1] "Down";Direction[Direction["Left"] 2] "L…

CTF靶场搭建及Web赛题制作与终端docker环境部署

♥ ♡ ♥ ♡ ♥ ♡ ♥ ♡ ♥ ♡ ♥ ♡ ♥ ♡ ♥ ♡ ♥ ♡ ♥ ♡ ♥ ♡ ♥ ♡ ♥ ♡ ♥ ♡ ♥ ♡ ♥ ♡ ♥ ♡ ♥ ♡ ♥ ♡ ♥ ♡ ♥ ♡ ♥ ♡ ♥ ♡ ♥ 写在前面 ╔═══════════════════════════════════════════════════…

Servlet---HttpServlet、HttpServletRequest、HttpServletResponseAPI详解

文章目录 HttpServlet基础方法doXXX方法Servlet的生命周期 HttpServletRequest获取请求中的信息获取请求传递的参数获取 query string 里的数据获取form表单里的数据获取JSON里的数据如何解析JSON格式获取数据返回数据 HttpServletResponse设置响应的Header设置不同的状态码设置…

羊大师教你如何有效解决工作中的挑战与压力?

在现代社会&#xff0c;工作问题一直是许多人头疼的难题。无论是从工作压力到职业发展&#xff0c;工作问题不仅会影响个人的心理健康&#xff0c;还可能对整个工作团队的效率和和谐产生负面影响。因此&#xff0c;如何有效解决工作问题成为了每个职场人士都需要面对的挑战。 …

性能测试:系统架构性能优化思路

今天谈下业务系统性能问题分析诊断和性能优化方面的内容。这篇文章重点还是谈已经上线的业务系统后续出现性能问题后的问题诊断和优化重点。 系统性能问题分析流程 我们首先来分析下如果一个业务系统上线前没有性能问题&#xff0c;而在上线后出现了比较严重的性能问题&#x…

sonar对webgoat进行静态扫描

安装sonar并配置 docker安装sonarqube&#xff0c;sonarQube静态代码扫描 - Joson6350 - 博客园 (cnblogs.com) 对webgoat进行sonar扫描 扫描结果 bugs Change this condition so that it does not always evaluate to "false" 意思是这里的else if语句不会执行…

如何训练专属的OCR文字识别模型

1. 背景 在10月24日程序员节&#xff0c;公司决定向每位技术人员发放购物实体卡以示庆祝。然而&#xff0c;手动输入实体卡上的一大串卡密可能是一项繁琐且不那么智能的任务&#xff1b;同时&#xff0c;线上用户在绑定购物卡的时候&#xff0c;同样也是需要手动输入。 基于以…

城市易涝点监测,内涝积水监测仪的作用

近些年城市内涝问题格外突出&#xff0c;市民心中总在担心是不是哪一天自己的家园因为内涝&#xff0c;从而短时间内无法正常生活。并且内涝过后的淤泥可能堆积到路边或者居民住宅区等地&#xff0c;这会影响城市生态环境和公共卫生。 内涝积水监测仪为解决城市内涝问题提供了更…

专业远程控制如何塑造安全体系?向日葵“全流程安全闭环”解析

安全是远程控制的重中之重&#xff0c;作为国民级远程控制品牌&#xff0c;向日葵远程控制就极为注重安全远控服务的塑造。近期向日葵发布了以安全和核心的新版“向日葵15”以及同步发布《贝锐向日葵远控安全标准白皮书》&#xff08;下简称《白皮书》&#xff09;&#xff0c;…

Redis性能压测、监控工具及优化方案

Redis是一款高性能的开源缓存数据库&#xff0c;但是在实际应用中&#xff0c;我们需要对Redis进行性能压测、监控以及优化&#xff0c;以确保其稳定性和高可用性。本文将介绍Redis性能压测、监控工具及优化方案。 01 Redis性能压测 常用的Redis性能压测工具有&#xff1a; …

git的实验:cherry-pick,github对比代码的两种方式

某个commit&#xff0c;比如 c1&#xff0c;&#xff0c;最早是在a分支做的&#xff0c;当被cherry-pick到b分之后&#xff0c;还是一样的revision吗&#xff1f; 实验1&#xff1a;c1被cherry-pick到别的分支后&#xff0c;revision不变对吗&#xff1f;&#xff08;答案是变…

在矩池云使用安装AgentTuning

AgentTuning 是清华大学和智谱AI共同推出的 AI Agent方案。 AgentTuning可以令LLM具备更强大的泛化能力&#xff0c;而且同时保持其通用语言能力&#xff0c;项目中包含的AgentInstruct 数据集和 AgentLM 模型均已开源。 项目地址&#xff1a;https://github.com/THUDM/Agent…