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

news2024/9/20 14:49:39

  

文章目录

    • 前置提要:
    • 解决方法:
    • 调试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());
                }

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

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

相关文章

UVA11584划分成回文串 Partitioning by Palindromes

划分成回文串 Partitioning by Palindromes 题面翻译 回文子串(palind) 问题描述&#xff1a; 当一个字符串正序和反序是完全相同时&#xff0c;我们称之为“回文串”。例如“racecar”就是一个回文串&#xff0c;而“fastcar”就不是。现在给一个字符串s&#xff0c;把它分…

【擎标】CCID信息系统服务商交付能力等级认证标准

为顺应信息技术服务业发展趋势及市场需求&#xff0c;维护市场秩序&#xff0c;加强行业自律&#xff0c;促进信息系统服务商交付能力的不断提高&#xff0c;增强信息系统服务商创新能力和国际竞争力&#xff0c;支撑信息系统服务商转型提升&#xff0c;中国软件行业协会、企业…

数字化时代,企业数据治理成熟度如何建设

企业数字化转型不是从0到1&#xff0c;而是从1到100。转型是一个过程&#xff0c;场景从简单到复杂&#xff0c;应用从局部到广泛&#xff0c;持续优化、逐步成长。 数据治理的成熟度评估模型 可以说&#xff0c;几乎所有成熟度模型都借鉴了CMM的思路&#xff0c;基本都是将所…

2023 极客巅峰线上

linkmap 考点: 栈溢出ret2csu栈迁移 保护: 开了 Full RELRO 和 NX, 所以这里不能打 ret2dl 题目给了一些有用的函数: 在这个函数中, 我们可以把一个地址的数据存放到 BSS 段上. 漏洞利用 可以把一个 libc 地址比如 readgot 读取到 bss 上, 然后在修改其为 syscall. 后面就是…

Grafana Panel组件跳转、交互实现

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一份大厂面试资料《史上最全大厂面试题》&#xff0c;Springboot、微服务、算法、数据结构、Zookeeper、Mybatis、Dubbo、linux、Kafka、Elasticsearch、数据库等等 …

实验4.数据全量、增量、比较更新

【实验目的】 1.利用Kettle的“表输入”&#xff0c;“表输入出”&#xff0c;”JavaScript代码”组件&#xff0c;实现数据全量更新。 2.熟练掌握“JavaScript代码”&#xff0c;“表输入”&#xff0c;“表输入出”组件的使用&#xff0c;实现数据全量更新。 【实验原理】 …

软件第三方测评报告可作哪些用途?

软件第三方测评报告是指由独立、中立的第三方机构对软件进行全面、客观、科学的评估和分析后所做的报告。该报告基于系统而严密的评测流程&#xff0c;通过多项指标和标准&#xff0c;对软件的性能、功能、易用性、安全性等方面进行评价&#xff0c;为用户提供一个权威、可靠的…

D. Absolute Beauty - 思维

题面 分析 补题。配上题解的图&#xff0c;理解了很长时间&#xff0c;思维还需要提高。 对于每一对 a i a_i ai​和 b i b_i bi​&#xff0c;可以看作一个线段的左右端点&#xff0c;这是关键的一步&#xff0c;那么他们的绝对值就是线段的长度&#xff0c;对于线段相对位…

PaddleOCR 运行退出0xC0000409,不显示错误信息

在一台老的电脑上去运行PaddleOCR 时&#xff0c;发现程序输出ppocr DEBUG: Namespace后&#xff0c;返回错误码0xC0000409执行到ocr就闪退&#xff0c;不提示。 原因&#xff1a;PaddleOCR 吞了输出。 解决方案 需要改下Pycharm的运行选项&#xff0c;勾选重定向也就是在输出…

Influence Matters 成立印度尼西亚办公室,构建北亚及东南亚服务中心

2023 年 11 月 22 日——过去八年&#xff0c;Influence Matters致力于通过高效的公关传播服务&#xff0c;为跨境B2B 科技企业耕耘中国市场提供业务支持。我们已与近百家企业、组织和政府合作&#xff0c;以远超预期的公关传播方案和执行力&#xff0c;为客户与其目标决策者和…

Windows配置Anaconda环境

1、下载Anaconda 2、安装Anaconda 2.1、系统环境变量 注&#xff1a; 将Anaconda添加到系统环境变量中&#xff0c;此处建议选中&#xff0c;可以省去好多麻烦 2.2、手动配置环境变量 系统—高级系统设置—环境变量—Path—新建&#xff1b;将下面的路径添加到环境变量中…

游戏开发引擎Cocos Creator和Unity如何对接广告-AdSet聚合广告平台

在游戏开发方面&#xff0c;游戏引擎的选择对开发过程和最终的产品质量有着重大的影响&#xff0c;Unity和Cocos是目前全球两大商用、通用交互内容开发工具&#xff0c;这两款引擎受到广泛关注&#xff0c;本文将从多个维度对两者进行比较&#xff0c;为开发者提供正确的选择建…

现代计算与光学的跨界机遇——

时至今日&#xff0c;互补氧化金属半导体&#xff08;CMOS&#xff09;技术的飞速发展促进了集成电路的空前成功。 晶体管的创新与时俱进 正如戈登-E-摩尔&#xff08;Gordon E. Moors&#xff09;在1965年预测的那样&#xff0c;每隔18-24个月&#xff0c;计算芯片上的晶体管数…

如何查找批量企业的联系方式?

​我们都知道&#xff0c;企业的联系方式在企业的年报中就能找到&#xff0c;但是年报上的电话真的是你要找的吗&#xff1f; 很多企业年报上留的是第三方代记账公司&#xff0c;或者是其他没用的号码&#xff0c;这对于做B端业务的企业来说是不够精准的。 市面上有很多做企业…

③【List】Redis常用数据类型: List [使用手册]

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ Redis List ③Redis List 操作命令汇总1. lpus…

员工微信私下收红包,企业如何加强监管

随着智能手机的普及和社交软件的兴起&#xff0c;越来越多的企业和员工开始使用微信等社交应用程序进行日常工作交流和业务协作。然而&#xff0c;与此同时&#xff0c;一些行业的员工在微信上私下收取红包的问题也日益严重&#xff0c;这不仅违反了公司的规定&#xff0c;也损…

口袋参谋:只用一招,提前规避差评!请看具体操作步骤

​如何提前规避差评&#xff1f;至少99%的商家都不知道该怎么做&#xff0c;剩下的1%还是我刚教会的。 宝贝的评价直接影响宝贝转化&#xff0c;特别是新品链接。 10个好评也挽回不了一个差评对产品的致命打击&#xff0c;差评就像一个重磅炸弹&#xff0c;威力足够能让你的转…

普乐蛙VR航天航空巡展项目来到了第七站——绵阳科博会

Hi~ 你有一份邀约请查收 11月22日—26日绵阳科博会 普乐蛙展位号&#xff1a;B馆科技体验区(1) 邀你体验趣味VR科普&#xff0c;探索科技新发展 第十一届中国(绵阳)科技城国际科技博览会 绵阳科博会自2013年创办以来&#xff0c;已连续成功举办十届&#xff0c;已有近7000家单位…

第四十篇,杂记(四)

增量式PID控制输出的是控制量增量&#xff0c;并无积分作用&#xff0c;因此该方法适用于执行机构带积分部件的对象&#xff0c;如步进电机等&#xff1b;在PID增量算法中&#xff0c;执行元件本身是机械或物理的积分储存单元&#xff1b;对输入加一个前置滤波器&#xff0c;使…

ADManager Plus:全能Active Directory管理的得力助手

一、简介 ADManager Plus是一款功能强大的Active Directory&#xff08;AD&#xff09;管理工具&#xff0c;为企业提供了全面、高效的AD管理解决方案。它不仅简化了AD管理的复杂性&#xff0c;还提高了管理员的工作效率。作为一款综合性的工具&#xff0c;ADManager Plus涵盖…