java - 如何在 .JAR 文件中执行此代码,但在 IDE 中有效
问题描述
当我在我的 Ide IntelliJ 中执行此代码时,它运行良好。但是当我最终在我的文件 .JAR 中执行此操作时,它不起作用。
@Throws(IOException::class)
fun extractZipMachineFromJar(file: String?, destination: String?) {
var `in`: ZipInputStream? = null
var out: OutputStream? = null
try { // Open the ZIP file
`in` = ZipInputStream((URL(file)).openStream())
// Get the first entry
var entry: ZipEntry? = null
while (`in`.nextEntry.also { entry = it } != null) {
val outFilename = entry!!.name
// Open the output file
if (entry!!.isDirectory) {
File(destination, outFilename).mkdirs()
} else {
out = FileOutputStream(File(destination, outFilename))
// Transfer bytes from the ZIP file to the output file
val buf = ByteArray(1024)
var len: Int
while (`in`.read(buf).also { len = it } > 0) {
out.write(buf, 0, len)
}
out.close()
}
}
} finally { // Close the stream
`in`?.close()
if (out != null) {
out.close()
}
}
}
在我点击的按钮中
val file = File(System.getProperty("user.dir") + "\\src\\main\\kotlin\\extractFolder\\myFiles.zip").path.toString()
extractZipMachineFromJar(file, folderWhereIExtractTo)
我怀疑这就是我设法访问 .Jar 文件中的资源的方式。但我不知道,因为当我从我的 IDE 执行它时它可以工作。
有谁知道这个代码示例如何在 .JAR 文件中工作?
我正在使用 IntelliJ IDEA 2019.3.5 社区版、Kotlin 1.3.70、Java 1.8.0_271、Java Fx 8.0.241、TornadoFX 1.7.20、Windows 10 19041.746
谢谢
更新:
我尝试了这个解决方案,但我认为我错误地应用了正确的代码。
引起:java.lang.IllegalStateException: MainView::class.java.get.../myFiles.zip") 不能为空
这是我的项目、文件夹和文件的修改代码和屏幕截图。
@Throws(IOException::class)
fun extractZipMachineFromJar(url : URL, destination: String?) {
var `in`: ZipInputStream? = null
var out: OutputStream? = null
try { // Open the ZIP file
`in` = ZipInputStream(MainView::class.java.getResourceAsStream(url.toString()))
// Get the first entry
var entry: ZipEntry? = null
while (`in`.nextEntry.also { entry = it } != null) {
val outFilename = entry!!.name
// Open the output file
if (entry!!.isDirectory) {
File(destination, outFilename).mkdirs()
} else {
out = FileOutputStream(File(destination, outFilename))
// Transfer bytes from the ZIP file to the output file
val buf = ByteArray(1024)
var len: Int
while (`in`.read(buf).also { len = it } > 0) {
out.write(buf, 0, len)
}
out.close()
}
}
} finally { // Close the stream
`in`?.close()
if (out != null) {
out.close()
}
}
}
val url : URL = MainView::class.java.getResource("/folderWithZip/myFiles.zip")
extractZipMachineFromJar(url, rutaCarpetasDLLMasBinDentro)
这是我的 MainApp.kt
fun main() {
launch<MainApp>()
}
class MainApp : App(MainView::class) { // me inyecta una clase
override fun start(stage: Stage) {
stage.minHeight = pantallaProgramaAlto
stage.minWidth = pantallaProgramaAncho
stage.resizableProperty().set(true)
super.start(stage)
}
和 MainView 类
class MainView : View(versionBarra) {
override val root = tabpane() {
tab<TabView>()
}
}
构建.gradle
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.3.70'
id 'com.github.johnrengelman.shadow' version '5.2.0'
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation "no.tornado:tornadofx:1.7.20"
implementation "com.squareup.okhttp3:mockwebserver:4.4.0"
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
//Definir clase principal para jar.
def mainClassName = 'playlistoPaquetorro.MainAppKt'
jar {
manifest {
attributes(
'Main-Class': mainClassName
)
}
}
解决方案
是的,current-working-dir/src/main/kotlin/blabla
显然不能保证存在。current-working-dir 不保证有用,此代码已损坏。
与已编译的类文件一样,属于应用程序一部分的资源应使用MyClass.class.getResource("relative-path.txt")
. 这将从 JVM 加载类文件的完全相同的位置加载文件。具体来说,该指令将查看 JVM 找到的“目录” MyClass.class
(具有表示 MyClass 类的字节码的类文件,该类文件可能位于磁盘上、jar 文件中、jmod 中或数据库中,或者动态生成 - 类加载系统非常抽象!) - 并在那里查找文件relative-path.txt
。即使它在该数据库中,在 jar 文件、jmod 文件等中。
用斜杠开始你的“相对路径”,它看起来相对于类路径根目录(所以,如果你有一个带有/com/foo/yourapp/Main.class
and的 jarfile /img/open.png
,Main.class.getResource("/img/open.png")
这就是你想要的。
.getResource
为您提供一个 URL 对象,可以将其传递给例如摇摆 JLabels 等。.getResourceAsStream
给你一个输入流(确保在 try-with-resources 构造中调用它!)。
File
是一个非首发。文件只能代表实际文件(因此得名),Java 应用程序通常不作为“一堆文件”提供。它们以“一个 jar 文件或一堆 jar 文件”的形式提供。里面的东西是 jar 文件中的条目,而不是文件。java.io.File
不能代表他们。
- 编辑 -
问题更新后:
顾名思义,这
src/main/kotlin
就是您的 kotlin 文件所在的位置。zip 不是 kotlin 文件。把那些放进去src/main/resources
。url.toString()? 我不知道你想对所有这些并发症做什么。只需先从硬编码的字符串开始,而不是这种复杂的混乱。一旦你弄清楚它是如何工作的,就可以随意抽象了。
推荐阅读
- c# - 如何使用 .ToString() 指定十进制类型的位数
- angular - 类型“OperatorFunction<{},any>”上不存在属性“订阅”
- python - 从类实例中访问 staticmethod 的正确/首选方式
- javascript - 使用WordPress,有动态查询,想避免缓存结果
- python - 如何根据多个条件过滤列表?
- ruby-on-rails - 对于 Rails 6 网站,Heroku 上的 .well-known 文件夹在哪里?
- angular - 定期检查令牌有效性 Angular
- java - 缩短 DynamoDB 中 @DynamoDBAutoGeneratedKey 的长度?
- kubernetes - 试图摆脱 heketi 中的孤立卷会导致无缘无故的错误
- java - Java中的优先队列堆