【发布时间】:2017-01-27 17:56:37
【问题描述】:
我有一个想要迁移到 J# 的 Visual J++ 项目。该代码不使用任何 Microsoft 特定的 API(如 WFC)或非标准语言扩展,因此从技术上讲,它完全符合 Java 1.1。
唯一的问题是资源(在 Java 世界中通常使用Class.getResourceAsStream() API 访问)。
在J++中,在项目配置中指定资源文件名模式就足够了,模式匹配的所有资源都会嵌入到生成的*.exe中(作为本机Win32资源)并且可以使用Class.getResourceAsStream()以编程方式访问,也可以使用任何resource editor手动访问:
问题
一旦项目迁移到 Visual J# (VS 2005),我立即失去了加载任何资源的能力(Class.getResourceAsStream() 开始返回 null 值),尽管“构建操作”对于每个感兴趣的资源,设置都设置为“嵌入式资源”:
并且资源实际上嵌入到程序集中(可以通过增加的 *.exe 文件大小来确认;此外,我确实使用dotPeek 工具看到了这些资源)。使用以下模式生成唯一资源名称:
<assembly's default namespace>.<Java package>.<file name with extension>
所以如果我有一个名为README.txt 的文件嵌套在com.example 包下,则生成的程序集资源名称将为default.com.example.README.txt:
Visual Studio 2003 的行为与 2005 版本不同:Class.getResourceAsStream() 不返回任何 null,但 mscorlib.dll 在运行时抛出 ArgumentOutOfRangeException:
mscorlib.dll!System.String.Substring(int startIndex = 0, int length = -1) + 0xbb bytes
vjslib.dll!com.ms.vjsharp.lang.VJSClassLoader.__findResource(System.Reflection.Assembly currentAssembly = {System.Reflection.Assembly}, string resName = "com/example/README.txt") + 0xc5 bytes
vjslib.dll!com.ms.vjsharp.lang.VJSClassLoader.__getResourcefromAssembly(System.Reflection.Assembly callingAssembly = {System.Reflection.Assembly}, string resName = "com.example.Main/+/com/example/README.txt") + 0x1b7 bytes
vjslib.dll!com.ms.vjsharp.lang.VJSClassLoader.getResourceAsStream(string resName = "com.example.Main/+/com/example/README.txt") + 0x57 bytes
vjslib.dll!java.lang.Class.getResourceAsStream(string resourceName = "com.example.Main/+/com/example/README.txt") + 0x10d bytes
test-resource-loading.exe!com.example.Main.main(String[] args = {Length=0}) Line 21 + 0x26 bytes
--但我相信这只是.NET Framework 2.0版本中修复的一个bug。
com.ms.vjsharp.lang.VJSClassLoader 显然不是我可以直接玩的公共课程。
尝试的解决方法
- 将相对资源路径替换为绝对路径,将点替换为斜线,反之亦然,带或不带前导斜线,带或不带默认程序集命名空间 - 无效。
-
使用
javac编译器将整个项目编译成可执行的*.jar,并将生成的JAR 提供给J# 二进制转换器工具 (jbimp.exe)——这不是一个选项。 J# Binary Converter Tool 由于其局限性几乎没用(我尝试了两个版本——来自 VS 2003 和 VS 2005):- 在 Java 字节码中对
Class.getResourceAsStream(...)的一次调用会导致在运行时抛出System.InvalidProgramException,尽管字节码到 MSIL 的转换是成功的。 -
只要有一个 try-finally 块(这就是流 I/O 通常在 Java 中完成的方式),
jbimp.exe就会失败并显示这些消息(我放弃尝试重写 5 行只是从文件中读取的代码块):JbImp error: Internal Conversion Error : 'exc-unclosed-blocks' JbImp error: Failed to create type for class 'com/example/Main'. Creating stub type JbImp error: Internal Conversion Error : 'JbImp fatal error: Conversion failed'
- 在 Java 字节码中对
-
来自 VS 2003/2005 的 J++ 项目迁移向导 没有帮助:它只会忽略任何未从
*.rc/*.res文件中引用的资源。 - 手动创建一个
*.resx文件,添加所有资源并完全摆脱Class.getResourceAsStream()调用(更改Java代码以加载资源为System.String(用于文本)和System.Drawing.Bitmap(用于图像)) .这是唯一可行的方法,但如果您的项目中有几十个小的*.gif文件,它会变得非常乏味。
问题
为什么Class.getResourceAsStream() 的vjslib.dll 实现不能按预期工作?我在这里错过了什么?
【问题讨论】:
标签: .net embedded-resource j# j++ visualj#