我有一个 Visual J ++ 项目,我想迁移到 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
,但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
- 但我相信这只是2.0版本的 .NET Framework 中修复的错误。
com.ms.vjsharp.lang.VJSClassLoader
显然对我来说不是一个公共课程,可以直接使用它。
使用javac
编译器将整个项目编译为可执行文件* .jar,并将生成的JAR提供给 J#Binary Converter Tool (jbimp.exe
) - 不是一种选择。 J#Binary Converter Tool 由于其局限性而几乎无用(我试过两个版本 - 来自VS 2003和VS 2005):
Class.getResourceAsStream(...)
进行单次调用会导致System.InvalidProgramException
在运行时抛出,尽管MSIL转换的字节码成功。每当有一个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'
J ++项目迁移向导没有帮助:它只是忽略未从*.rc
/ *.res
文件引用的任何资源。
*.resx
文件,向其添加所有资源并完全删除Class.getResourceAsStream()
调用(更改Java代码以将资源加载为System.String
(对于文本)和{{ 1}}(用于图像))。这是唯一可行的方法,但如果您的项目中有几十个小System.Drawing.Bitmap
个文件,那就变得非常繁琐。为什么*.gif
vjslib.dll
的实施工作没有按预期进行?我在这里缺少什么?
答案 0 :(得分:0)
Microsoft 在 J#运行时中实现的 Java API的文档很模糊(特别是Class.getResourceAsStream()
个州的页面与 J ++ 不同, J#中不支持此方法,是解决方案。
进一步研究表明,除了自定义class loaders(已被删除)之外,所有 Java 1.1 甚至一些 Java < / em> 1.2 API已经实施 - 包括collections和Swing。
说到资源,How to: Upgrade Visual J++ 6.0 Applications That Use Resources文章涵盖了这些内容。可以使用 Visual Studio 2005 应用程序示例附带的vjsresgen.exe
实用程序将 Java 样式资源转换为.resx
,源代码可从< EM>微软
每个资源都转换为字节数组。以下是在 Visual Studio 中打开的示例vjsresgen.exe
生成的.resx
文件的屏幕截图: