首页 > 解决方案 > 如何在 .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
        )
    }
}

标签: javakotlinintellij-ideawindows-10javafx-8

解决方案


是的,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.classand的 jarfile /img/open.pngMain.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()? 我不知道你想对所有这些并发症做什么。只需先从硬编码的字符串开始,而不是这种复杂的混乱。一旦你弄清楚它是如何工作的,就可以随意抽象了。


推荐阅读