我有一个想要迁移到J#的Visual J++项目。该代码不使用任何 Microsoft 特定的 API(如WFC)或非标准语言扩展,因此从技术上讲,它完全符合 Java 1.1。
唯一的问题是资源(在 Java 世界中通常使用Class.getResourceAsStream()
API 访问)。
在J++中,在项目配置中指定资源文件名模式就足够了,与模式匹配的所有资源都将嵌入到生成的 *.exe 中(作为本机 Win32 资源),并且可以通过编程方式使用Class.getResourceAsStream()
和手动使用任何资源进行访问编辑:
问题
一旦项目迁移到Visual J#(VS 2005),我立即失去了加载任何资源(Class.getResourceAsStream()
开始返回null
值)的能力,尽管每个感兴趣的资源的“构建操作”设置都设置为“嵌入式资源”:
并且资源实际上嵌入到程序集中(可以通过增加的 *.exe 文件大小来确认;此外,我确实使用dotPeek工具看到了这些资源)。使用以下模式生成唯一资源名称:
<assembly's default namespace>.<Java package>.<file name with extension>
因此,如果我在包下有一个名为README.txt
nested的文件com.example
,则生成的程序集资源名称将是default.com.example.README.txt
:
Visual Studio 2003的行为与 2005 版本不同:Class.getResourceAsStream()
不返回任何内容null
,但在运行时ArgumentOutOfRangeException
被抛出:mscorlib.dll
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 版本中修复的一个错误。
com.ms.vjsharp.lang.VJSClassLoader
显然不是我可以直接玩的公共课程。
尝试的变通方法
- 用绝对路径替换相对资源路径,用斜线替换点,反之亦然,带或不带前导斜线,带或不带默认程序集命名空间 - 无效。
使用编译器将整个项目编译成可执行的 *.jar
javac
并将生成的 JAR 提供给J# Binary Converter Tool (jbimp.exe
) - 这不是一个选项。J# Binary Converter Tool由于其局限性而几乎没用(我尝试了两个版本——来自 VS 2003 和 VS 2005):- 尽管字节码到 MSIL 的转换成功,但对 Java 字节码的单个调用会
Class.getResourceAsStream(...)
导致在运行时抛出。System.InvalidProgramException
每当有一个 try-finally 块(这通常是在Java中完成流 I/O 的方式)时,
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'
- 尽管字节码到 MSIL 的转换成功,但对 Java 字节码的单个调用会
来自 VS 2003/2005 的J++ 项目迁移向导没有帮助:它只是忽略任何未从
*.rc
/*.res
文件引用的资源。- 手动创建一个
*.resx
文件,向其中添加所有资源并完全摆脱Class.getResourceAsStream()
调用(更改 Java 代码以将资源加载为System.String
(对于文本)和System.Drawing.Bitmap
(对于图像))。这是唯一可行的方法,但是如果您*.gif
的项目中有几十个小文件,它就会变得非常乏味。
问题
为什么没有vjslib.dll
按Class.getResourceAsStream()
预期工作?我在这里想念什么?