2011-06-24 63 views
12

我是OSGi的新手,并创建了一个在Apache Felix OSGi容器中运行的OSGi包。 包中包含文件资源,我需要将其传递给方法java.io.File。要实例化File对象,“文件” - 方案中的URI或字符串路径是必需的。我如何以干净的方式检索这些内容?如何访问OSGi包内的文件?

我尝试使用 context.getBundle().getResource("/myfile")(其中上下文类型为org.osgi.framework.BundleContext),它返回URI bundle://6.0:0/myfile。 但是由于该URI具有“bundle”方案,因此无法使用File(URI uri)构造函数将其转换为File-instance。

可以尝试构建知道工作目录并利用bundle的bundleId的路径,但我怀疑这是最佳实践。

任何想法?

+0

春分具有特殊的实用工具类,在面向未来的方式做这样的转换,但我不知道费利克斯。如果您想要使用干净的OSGi API进行编码,则需要将该文件复制到某处,以便轻松检索相应的File对象(例如,在您的Bundle.getDataFile()存储中)。 –

回答

12

由于文件是里面的你的包,你无法使用标准的File去它。您从Bundle.getResource()获得的URL是获得这些资源的正确方式,因为OSGi API也适用于没有实际文件系统的系统。我会一直试图坚持使用OSGi API,而不是使用框架特定的解决方案。因此,如果您对该方法有控制权,我会更新它以采用URL,或者甚至可能是InputStream(因为您可能只是想阅读它)。为方便起见,您可以随时提供确实需要File的帮助方法。

如果你没有过的方法控制,你将不得不写一些辅助方法,是以URL,流出来的文件(例如,File.createTempFile()可能会做的伎俩。

+0

感谢您的回答。我无法控制该方法,因为它是我无法修改的依赖项,并且此依赖项指示File类型的参数。要解释您的答案:建议通过InputStream访问文件,并将其作为临时文件写入通过OSGi-API引用的包的专用区域。这是一般的最佳做法吗?因为使用这种技术,资源在物理内存中翻倍。假设你有多个文件,它们都会翻倍,这可能是小设备上的一个问题。或者我错过了一点? – mtsz

+0

你是绝对正确的,这是一种低效率,由OSGi之间的哲学差异(“每个资源都有一个URL,即使我们没有文件”)和你的库(“我必须有一个文件” )。您可以使用临时文件,也可以使用捆绑存储;最适合你的情况。 –

+1

安杰洛是正确的...你使用的图书馆设计得很差。它坚持要给它一个文件,但是你所拥有的不是一个文件,而是一个文件的片段(从技术上说,是一个ZIP的输入)。效率低下是不可避免的。 –

6

也许该API是混淆的,但您可以访问一个OSGi包这样的内部文件:

URL url = context.getBundle().getResource("com/my/weager/impl/test.txt"); 

// The url maybe like this: bundle://2.0:2/com/my/weager/impl/test.txt 
// But this url is not a real file path :(, you could't use it as a file. 
// This url should be handled by the specific URLHandlersBundleStreamHandler, 
// you can look up details in BundleRevisionImpl.createURL(int port, String path) 
System.out.println(url.toString()); 

BufferedReader br =new BufferedReader(new InputStreamReader(url.openConnection().getInputStream())); 
while(br.ready()){ 
    System.out.println(br.readLine()); 
} 
br.close(); 

getResource会发现在整个OSGI容器就像OSGI类加载器的理论资源
getEntry会发现RESOUR ce从本地捆绑。并且返回url可以被转换为文件,但可以是inputStream。
以下是与此相同的问题:No access to Bundle Resource/File (OSGi) 希望这对你有所帮助。

1

我用的是什么getClassLoader()的getResourceAsStream():

InputStream inStream = new java.io.BufferedInputStream(this.getClass().getClassLoader().getResourceAsStream(fileName)); 

这样该文件会从你的资源目录加载。 FileName应包含“src/main/resources”之后的路径。

完整的示例在这里:

static public byte[] readFileAsBytes(Class c, String fileName) throws IOException { 
    InputStream inStream = new java.io.BufferedInputStream(c.getClassLoader().getResourceAsStream(fileName)); 
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    int nbytes = 0; 
    byte[] buffer = new byte[100000]; 

    try { 
     while ((nbytes = inStream.read(buffer)) != -1) { 
      out.write(buffer, 0, nbytes); 
     } 
     return out.toByteArray(); 
    } finally { 
     if (inStream != null) { 
      inStream.close(); 
     } 
     if (out != null) { 
      out.close(); 
     } 
    } 
}