如何在jar内的jar内访问一个非类文件

时间:2012-11-27 15:33:17

标签: java jar

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

在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

这怎么可能很难?!!

----------添加了INFO ------ n

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

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

根据FileInputStream(String name)的文档是

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

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

简而言之,答案是你做不到的。至少在这种情况下。我坚持将文件路径传递给我无法控制的库实现。因此,库方法在假设文件在OS的文件系统中以解压缩的形式存在的情况下访问该文件。它是从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;
}