【问题标题】:How can I access a non-class file inside a jar FROM 'within' the jar如何从 jar 中的“内部”访问 jar 中的非类文件
【发布时间】:2012-11-15 06:30:56
【问题描述】:

这应该很简单,但花了我几个小时。我在这个网站上找到的所有内容都表明我做得对,但仍然找不到该文件。

在一个 jar 文件中,我在顶层有两个文件“CDAkeystore.jks”和“CDAtruststore.jks”。 然而当我打电话时 securityProps.setProperty("javax.net.ssl.keyStore","CDAkeystore.jks"); 我收到系统找不到请求的文件错误。 调用此方法的类文件在通常的包排列中位于同一个 jar 中。

jar文件如下:

com ..... (a lot more class files)
org ..... (lots of class files)
META-INF
CDAtruststore.jks
CDAkeystore.jks

这怎么会这么难?!!

------添加信息-----n

由于使用路径的对象是开源的,我找到了他们用来加载文件的例程。它是:

InputStream keystoreInputStream = preBufferInputStream(new FileInputStream(keyStoreName));

根据 FileInputStream(String name) 的文档是

通过打开与实际文件的连接来创建 FileInputStream,该文件由文件系统中的路径名“name”命名。那么这条路径应该如何表达呢?

【问题讨论】:

  • 是的,但不幸的是它的库代码正在抓取文件;我只需要将路径作为字符串提供。库代码使用一个 Property 对象来获取各种值;文件的路径就是其中之一。

标签: java jar


【解决方案1】:

使用YourClass.class.getResourceAsStream()this.getClass().getResourceAsStream()。如果您在多个类加载器环境中,您也可以使用类加载器。

【讨论】:

  • 'setProperty()' 方法需要一个字符串,我认为它是现有文件的路径。我不想自己访问数据,但此代码正在获取设置 TLS 通信所需的信息。我只需要获取正确的路径,以便所有代码(我可能添加的引擎盖下)都可以获得密钥库并执行它的魔法。所以我应该更清楚;我不需要文件,只需要它的路径!
【解决方案2】:

简而言之,答案是您不能。至少在这种情况下。我坚持将文件路径传递给我无法控制的库实现。因此,库方法在文件以解压缩形式存在于操作系统文件系统中的假设下访问文件。它从 Property.setProperty(stringKey, stringPath) 获取路径 所以我找到的唯一解决方案是一个丑陋的黑客。我需要获取 jar 中的资源并将其复制到系统上的文件中。然后我会在上面的 setProperty() 方法中传递该文件的路径。丑陋的黑客实现如下(如果其他人能提出更好的解决方案,我会很高兴)。它确实解决了问题。库例程能够找到我新创建的文件。

/* This evil reads a file as a resource inside a jar and dumps the file where ever
 * the loader of this jar/application defines as the current directory. This pain is done
 * so the SecurityDomian class can load the file; it cannot access the file from
 * the jar. This means the 'name' passed in contains the file name inside the jar
 * prefixed with "/" so it is not read with an assumed package extension.
 */
private boolean createFileFromResource(String name)
{
    // Dont bother if the file already exists
    if(new File(name.replace("/", "")).exists())
    { 
        return true;
    }
    byte[] keystoreFile = new byte[2048];
    ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream(2048);
    // Get the resource
    InputStream inputStream = this.getClass().getResourceAsStream(name);
    try
    {
        int bytesRead = 0;
        while(true)
        {
            // Read the resource into the buffer keystoreFile in 2048 byte chunks
            bytesRead = inputStream.read(keystoreFile);
            if(bytesRead < 0)
            {
                break;
            }
            // Copy and append the chunks to the ByteArrayOutputStream (this class
            // does the auto-extending of the output array as more chunks are 
            // added so you don't have to do it.
            byteArrayOut.write(keystoreFile, 0, bytesRead);
        }
        inputStream.close();
        // Now create a file at the root of where ever the loader happens to think
        // the root is. So remove the "/" in front of the file name
        FileOutputStream outputStream = new FileOutputStream(name.replace("/", ""));
        // Write out the file. Note you will be left with garbage at that location.
        byteArrayOut.writeTo(outputStream);
        outputStream.flush();
        outputStream.close();
    } 
    catch (IOException e)
    {
        e.printStackTrace();
        return false;
    }
    return true;
}

【讨论】:

    猜你喜欢
    • 2017-11-27
    • 1970-01-01
    • 1970-01-01
    • 2011-06-30
    • 1970-01-01
    • 1970-01-01
    • 2013-03-13
    • 1970-01-01
    • 2015-09-06
    相关资源
    最近更新 更多