gpt4 book ai didi

vb.net - 解开关于嵌入式资源的困惑

转载 作者:行者123 更新时间:2023-12-03 00:56:04 24 4
gpt4 key购买 nike

编辑:阅读 Tim Schmelter 的答案 1,然后使用此问题作为示例,了解如何嵌入资源并在运行时访问它们。

嵌入式资源的主题出现了很多,尤其是人们询问如何在运行时访问嵌入式文件。事情变得更加困惑,因为 Visual Studio 为您提供了两种不同的嵌入资源的方式,以及在运行时访问这些资源的不同方式。问题在于,根据您用于嵌入资源的方法,您尝试在运行时访问文件的方法可能不起作用。这篇文章试图澄清我在那里看到的所有困惑,但我也有一个似乎没有人能够真正回答的问题:为什么我编译的程序的大小是嵌入资源大小的两倍(有时)?例如,如果我将一个 20MB 的文件嵌入到我的项目中,为什么我的程序会编译为 40MB?我过去曾问过这个问题,但没有人能够重现我的结果。我发现他们无法复制的原因是他们以不同的方式嵌入文件。看这里:

方法一:

双击“我的项目”打开属性页并转到“资源”选项卡。现在单击添加资源 > 添加现有文件。浏览到要嵌入的文件。在这个例子中,我使用了一个可执行文件。您现在将在“资源”选项卡上看到您的文件:

enter image description here

您还将看到在您的项目下创建了一个名为 Resources 的文件夹,并且嵌入的文件已放置在此文件夹中:

enter image description here

编辑:下一步是问题所在。事实证明,当您通过资源选项卡添加文件时,您不应该将构建操作设置为嵌入资源。 至少可以说反直觉!

现在选择文件后,向下查看文件的属性窗口并将构建操作更改为嵌入式资源: (仅当您通过方法 2 添加文件时才应执行此步骤)。

enter image description here

现在编译你的程序。您将看到编译程序的大小至少是嵌入资源大小的两倍。方法 2 不会发生这种情况。请参见此处:

方法二:

右键单击您的项目名称,然后选择添加 > 现有项目。浏览到您的文件,这一次您会注意到,虽然它确实放在您的项目下,但没有创建 Resources 文件夹:

enter image description here

现在再次选择该文件并将 Build Action 更改为 Embedded Resource 并进行编译。这次编译程序的大小将如您所料 - 大约是嵌入文件的大小,而不是方法 1 的两倍大小。

您用于嵌入文件的方法将决定您可以使用哪种方法在运行时访问文件。对于方法 1,这非常简单,您所要做的就是:

My.Computer.FileSystem.WriteAllBytes(Path, My.Resources.ResourceName, Append)

其中 Path 是您要保存在硬盘上的文件的位置和名称,ResourceName 是您在项目窗口中看到的嵌入资源的名称(减去任何扩展名),而 Append 是您是否要创建一个新建文件或覆盖现有文件。例如,使用上面图像中的 test.exe,我可以将该文件保存到 C 驱动器,如下所示:
My.Computer.FileSystem.WriteAllBytes(“C:\test.exe”, My.Resources.test, False)

再简单不过了。

然而,方法 2 似乎无法让您访问 My.Resources,因此它变得有点复杂。您必须创建一个 Stream 来保存资源,将流放入一个字节数组,然后将字节写入文件系统。我发现这样做的最简单方法是这样的:
Using s As Stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(Project.ResourceName)
Dim bytes(s.Length) As Byte
s.Read(bytes, 0, bytes.Length)
File.WriteAllBytes(OutputFile, bytes)
End Using

使用此方法 ResourceName 必须包含文件扩展名和项目名称,因此使用上面的示例,我们可以这样做:
Using s As Stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(WindowsApplication1.test.exe)
Dim bytes(s.Length) As Byte
s.Read(bytes, 0, bytes.Length)
File.WriteAllBytes(“C:\test.exe”, bytes)
End Using

基于文本的文件有点不同:
Dim output As String
Using sr As StreamReader = New StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(WindowsApplication1.test.txt))
output = sr.ReadToEnd()
End Using

Using sw As StreamWriter = New StreamWriter(“C:\test.txt”)
sw.Write(output)
End Using

过去曾为此苦苦挣扎,我希望这会对某人有所帮助。而且,如果您认为您可以真实地解释为什么嵌入资源的方法 1 会使我编译的程序膨胀以使其大小加倍,我将非常感激。

最佳答案

我假设方法 1 将文件添加两次。

  • http://www.vbdotnetforums.com/vb-net-general-discussion/42670-visual-basic-net-2008-get-resource-file-io-stream.html#post121923

  • 至少这是 thread above的结论.

    报价 :

    您转到项目属性的资源页面并在那里添加文件,对吗?然后您进入解决方案资源管理器并将文件的构建操作更改为嵌入式资源,对吗?这就是您将文件大小加倍的原因:您将每个文件添加了两次。

    添加资源有两种不同的方式:在项目属性的资源页面上和在解决方案资源管理器中。你不能两者都做。如果您想使用 GetManifestResourcestream,则不要使用资源页面。您在解决方案资源管理器中手动将文件添加到项目,然后将构建操作设置为嵌入式资源。

    将来,做一个或另一个,而不是两者。
  • 将文件添加到项目属性的资源页面,然后通过 My.Resources 访问它。这将自动将文件添加到解决方案资源管理器中的项目,但构建操作将为无,应保持原样。
  • 使用添加新项目或添加现有项目将文件添加到解决方案资源管理器中的项目。将文件的 Build Action 设置为 Embedded Resource,然后使用 GetManifestResourceStream 访问该资源。
  • 关于vb.net - 解开关于嵌入式资源的困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8851991/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com