简体   繁体   English

无法从jar获取资源

[英]Can't get resources from jar

In my project i need to take jsons from folder located in resources.在我的项目中,我需要从资源中的文件夹中获取 json。 For it I implemented this method:为此我实现了这个方法:

protected def getListOfJsonFromResources(path: String): List[String] = {
  val source = Source.fromInputStream(Thread.currentThread().getContextClassLoader.getResourceAsStream(path))
  println(source)
  val list = source.getLines().map{file =>
    Source.fromInputStream(Thread.currentThread().getContextClassLoader.getResourceAsStream(path + file))
      .mkString
  }.toList
  source.close()
  list
}

It's work fine in IDE but return nothing when I run my jar. I know that problem is in val source as in jar it return empty iterator.它在 IDE 中工作正常,但当我运行我的 jar 时没有返回任何内容。我知道问题出在val source中,因为在 jar 中它返回空迭代器。 I tried already use this.getClass().getResourceAsStream() , this.getClass().getClassLoader().getResourceAsStream() and rewrite this method as java method.我已经尝试使用this.getClass().getResourceAsStream()this.getClass().getClassLoader().getResourceAsStream()并将此方法重写为 java 方法。

I generate JAR in Idea (Build>Build Artifacts>Build).我在 Idea(Build>Build Artifacts>Build)中生成 JAR。 This files is inside JAR with correct path.此文件位于 JAR 内,路径正确。 I use Apache Maven 3.6.3 My res folder: resources/folder/json/jsonFolder path:folder/json/jsonFolder/我使用 Apache Maven 3.6.3 我的 res 文件夹:resources/folder/json/jsonFolder path:folder/json/jsonFolder/

How should I change this method to get list of jsons from given folder?我应该如何更改此方法以从给定文件夹中获取 json 列表?

Thank, in advance.预先感谢。

The proper usage is actually MyClass.class.getResourceAsStream .正确的用法实际上是MyClass.class.getResourceAsStream After all, getClass().getRAS() would fail if your code is subclassed.毕竟,如果您的代码被子类化, getClass().getRAS()将会失败。 However, I assume it isn't - so that change will improve the style of this code and future proof it, but it probably won't directly fix the issue.但是,我认为它不是 - 因此更改将改进此代码的样式并在未来证明它,但它可能不会直接解决问题。

What MyClass.class.getRAS does, is look in the exact same place that the MyClass.class file is at. MyClass.class.getRAS所做的是查看MyClass.class文件所在的完全相同的位置。 For example, if you have a jar with:例如,如果您有一个 jar:

META-INF/MANIFEST.MF
com/foo/app/MyClass.class
app-icon.png
com/foo/app/save.png

And you run MyClass, then MyClass.class.gRAS("save.png") will work out.然后你运行 MyClass,然后MyClass.class.gRAS("save.png")就会运行。 As weill MyClass.class.gRAS("/app-icon.png") - note the leading slash.正如MyClass.class.gRAS("/app-icon.png") - 注意前导斜杠。

Thus, if gRAS isn't working for you here, the conclusion is that you're either specifying the wrong path, or the file you need to be included with your app is not being included by your build tooling.因此,如果 gRAS 在这里不适合您,那么结论是您指定了错误的路径,或者您需要包含在应用程序中的文件未包含在您的构建工具中。

You haven't shown anything relevant from your build scripts, so there's not much to say about how to fix this.您没有显示任何与您的构建脚本相关的内容,因此关于如何解决这个问题没有太多可说的。 But I can give you the tools you need to debug the problem so you can fix it yourself, with this useful trick:但我可以为您提供调试问题所需的工具,这样您就可以使用这个有用的技巧自行修复它:

MyClass.class.getResource("MyClass.class")

works for any class. Print it ( System.out.println the URL that falls out of the above call), and you will see the URL, which tells you exactly which of the no doubt many variants of MyClass is actually being used (by your IDE's build-on-save, by sbt's build tooling, in the jar file produced by sbt during the dist phase, and who knows how many more exist somewhere on disk.).适用于任何 class。打印它( System.out.println上面调用中的 URL),您将看到 URL,它准确地告诉您实际使用了 MyClass 的许多变体中的哪一个(通过你的 IDE 的构建保存,由 sbt 的构建工具,在 dist 阶段由 sbt 生成的 jar 文件中,谁知道磁盘上的某个地方还有多少。)。

Now use standard computer tools (Mac: Finder, windows: Explorer, or just use the command line) to navigate to the actual location and check for the existence of this resource file.现在使用标准的计算机工具(Mac:Finder,windows:Explorer,或者只使用命令行)导航到实际位置并检查此资源文件是否存在。 Note that jar files are just zip files;请注意,jar 个文件只是 zip 个文件; unzip -l somejar.jar is useful here. unzip -l somejar.jar在这里很有用。

If you see the file, well, now you know where that file is relative to MyClass.class , and now you know what to feed to the gRAS call.如果您看到该文件,那么,现在您知道该文件相对于MyClass.class的位置,并且现在您知道向gRAS调用提供什么。 Note that .. is not a good idea;请注意..不是一个好主意; if it's not in the same dir as your class and not in any subdir, then use the leading slash to go off of the 'root' of the jar file or classpath root directory.如果它不在与您的 class 相同的目录中并且不在任何子目录中,则使用前导斜杠指向 jar 文件或类路径根目录的“root”之外的 go。

If you don't see the file, well, now you know that your build is broken.如果您没有看到该文件,那么,现在您知道您的构建已损坏。 Search the web (or ask in a separate question here on SO) on how to fix that, and now you don't need to repeatedly build and run the entire app to figure it out;搜索 web(或在 SO 上的单独问题中询问)以了解如何解决该问题,现在您无需重复构建和运行整个应用程序即可解决问题; you can simply keep scanning the jar file produced by the build tool until the resource file shows up in the right spot.您可以简单地继续扫描构建工具生成的 jar 文件,直到资源文件出现在正确的位置。

NB: ClassLoader.getSystemCLassLoader.getResource, getThreadContext().getResource, getClass().getResource - these are all wrong.注意:ClassLoader.getSystemCLassLoader.getResource、getThreadContext().getResource、getClass().getResource - 这些都是错误的。 Don't do that.不要那样做。 It'll probably also work, but it's more code and will break in various circumstances.它也可能会工作,但它的代码更多,并且会在各种情况下中断。 MyClass.class.getResource does exactly what you want, is idiomatic, and is one of the shortest forms. MyClass.class.getResource完全符合您的要求,是惯用的,并且是最短的 forms 之一。

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

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