繁体   English   中英

从与 JAR 文件相同的文件夹中读取文件,但从 IDE 加载时仍读取资源文件夹

[英]Read a file from same folder as JAR file but still read resources folder when loading from IDE

我一直在尝试制作可以读取与其位于同一目录中的 csv 文件的 jar 应用程序。 然而,事实证明这很困难,因为我目前访问文件的方法是:

InputStream is = getClass().getClassLoader().getResourceAsStream(filename);

这适用于我在 IDE 中运行的程序和我的测试,但当我从编译的 jar 文件运行程序时它不起作用。 我不知道如何让它对两者都有效。 我真的无法理解这条路径的东西,似乎有一百万种方法可以做到这一点,其中只有一种只适用于一个特定的场景。

我一直在尝试制作可以读取与其位于同一目录中的 csv 文件的 jar 应用程序。

啊,你的问题。 那不是一回事。

只有两种类型的文件:

应用资源

这些是只读的,并且与类文件一样是应用程序的一部分。 考虑“编辑”它们没有任何意义——它们不是那种东西。 可以合理地假设,如果此资源以某种方式丢失,则应用程序与类文件丢失时一样损坏/安装错误。

为此,您使用.getResource.getResourceAsStream 并注意getClass().getClassLoader()是错误的,如果你想从根目录开始,你想要MyClass.class.getResource然后添加一个斜杠(因为getClass()在你子类化时可能会中断,并且通过类加载器是 [A ] 只是无缘无故地打字,而 [B] 在引导加载场景中中断MyOwnClassName.class.getResource永远不会中断,所以,总是使用它)。

这要求 java 查找类文件所在的相同位置,而不是其他位置。 您的类文件jar 文件中,而不是在它们旁边,因此,它不会找到位于 jar 文件旁边的文本文件。

它在开发过程中确实有效是没有意义的:这意味着您将一个文件推到资源文件夹中,这相当于jar 文件中有一个 CSV 文件。 你一定是特意告诉你的构建系统做一些奇怪的事情。 不要那样做。

如果该 CSV 文件不打算供用户编辑,则它应该在 jar 文件内而不是在它旁边:这使它成为应用程序资源。 应用资源示例:

  • 你有一个 GUI,你需要在某个地方存储图标文件和启动画面艺术等。
  • 您使用您的应用程序发送静态数据,例如所有美国州的表格以及它们使用的邮政编码(例如可以是文本或 csv 文件)。
  • 配置文件的模板 不是配置文件本身。
  • 您需要解压缩的 DLL 等(因为 windows/linux/mac 不会在 jar 中查找它们)。
  • 您是一个 web 应用程序,并且您希望将 HTML 静态文件与您的 web 应用程序一起发送。

如果这是您的 CSV 文件,则解决方法是将其放在 jar 中,而不是放在它旁边,然后使用MyClass.class.getResource(name)加载它。

配置文件和项目文件

例如:

  • 对于富文本编辑器(例如 LibreOffice Writer),代表您的作品的.odt文件。
  • 为游戏保存游戏。
  • 一个配置文件,可以由用户编辑,或者由您自己的应用程序在“首选项”对话框中编辑。 这会存储例如是否全屏打开应用程序,或者您正在使用的第三方 API 的身份验证信息。

这些不应该在 jar 中,根本不应该使用.getResource加载,并且首先不应该在 src/main/resources 中

他们也不应该在你的罐子旁边! 这是一个过时且不安全的模型(可编辑文件位于应用程序本身所在的同一位置的想法):正确的操作系统配置意味着应用程序无法写入自身,这很容易通过使其无法写入其目录来实现. 一些操作系统(尤其是 Windows)在一段时间内犯了这个错误。

例如,在 Windows 上,您的应用程序位于C:\Program Files\MakorisAwesomeApp\makori.jar中,而它的数据文件位于C:\Users\UserThatInstalledIt\Documents\MakorisAwesomeApp中。

哦,Linux,您的应用程序可能是/usr/bin/makori并且数据位于主目录中的某个位置。 配置数据可能存在于/etc/中。

您不会“运送”您的配置文件,而是制作创建它们的安装程序。 您可以通过检测相关配置文件不存在来在应用程序中执行此部分,加载模板(资源,在您的 jar 中提供,加载getResource ),并将其写出来,并告诉用户去查看并编辑它。

我真的想要一个 CSV 文件在我的罐子旁边!

好吧,那是错误的,所以没有库可以让这变得简单。 当你想做一些愚蠢的事情时,API 不会那么容易,对吧?

确实有一些 hacky 方法可以做到这一点。 您可以使用 .getResource 获取 URL,然后“解析”它。 这打破了类加载器抽象概念(因为在 java 中,您可以编写自己的类加载器,它们可以从任何地方加载,而不仅仅是 jar 中的文件或条目),但您可以要求“你自己”( MyClass.class.getResource("MyClass.class") ),将 URL 拉开并弄清楚发生了什么 - 它是否以file://开头? 然后它是一个文件,所以把它变成一个jiFile对象,然后从那里开始。 它是否以jar://开头? 找到! ,子串出 jar 部分,现在你知道了 jar。 将其设为java.io.File ,询问父目录,然后在此处查找 CSV。

你必须写下这一切。 这是复杂的代码,很难测试。 你不应该这样做。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM