将文本文件嵌入资源中

6
我试图将一个文本文件嵌入到我的应用程序的资源文件中。我遵循了这个问题的帖子:

如何在.NET程序集中嵌入文本文件?

我将我的文本文件添加到Resources.resx中,但不知道如何在代码中调用它。正如您所看到的,OP也有同样的问题,并通过使用 My.Resources.TEXTFILENAME 而不是顶部答案的建议 Resources.TEXTFILENAME 来使其工作。不幸的是,两者都没有被我的应用程序识别,并且我已经尝试添加usings,但VS没有提供任何建议。单独写 Resources ,它会将其识别为ResourceDictionary和FrameworkElement.Resources,但没有文本文件......有什么想法吗?

4个回答

17

嵌入文本资源似乎能够正常工作(使用visual c# express):

  1. 打开项目属性:
    enter image description here

  2. 浏览到资源,点击添加新项并选择创建或添加已存在的资源,取决于情况。 enter image description here

  3. 出现一个资源文件夹: enter image description here

  4. 可以像这样使用它们:

string foo = global::[ProjectName].Properties.Resources.Muistio;
string bar = global::[ProjectName].Properties.Resources.asd;

资源生成操作为,并且复制到输出目录为不复制

如果有人可以验证一下这个,那就太好了,当.exe文件传输到我的服务器2k8时它是有效的,但我仍然想要独立的验证。尤其是因为ResourceHacker没有看到这些字符串。


1
+1 有用的截图。还有一个疯狂的资源文件夹...太棒了。 - windowsgm
是的,但你不能流式传输它。你必须使用@Nenotlep提到的属性,或者使用ResourceManager.GetString(name),但这会产生一个Unicode字符串 - 可能比文件大两倍。 - Eric
1
这在我的VS 2017中有效。截图非常有用。 - Rajaraman Subramanian
适用于Visual Studio 2019的工作... - undefined

6
将文本文件添加到您的项目中,然后将其定义为内容 (Build Action=Content) 并且选择 Copy always 到输出。
如果您为项目安装了安装程序(标准安装程序),则可以设置文件系统,以便安装程序会自动复制文本文件。
要获取应用程序运行的文件夹,我使用以下代码: Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly.Location); 如果您正在使用新的安装程序 (ClickOnce),我无法提供帮助,但是祝您好运 :=)

我实际上没有使用任何安装程序。只使用我生成的exe文件。 - windowsgm
1
但是那样做不会将文件嵌入到输出目录中,只会复制文件。 - Joel Peltonen
@Nenotlep:我想你是对的。我必须选择“Build Action=Resource”,而不是“Copy”。如果你确认了,我会更新的。如果你有更多信息,请毫不犹豫地发布答案。 - GameAlchemist

3
如果文件比较小,可以像其他人描述的那样使用项目资源文件,但这种方式只能将文件检索为Unicode字符串,可能/很可能比原始文件大两倍,并且一次性全部加载到内存中。
原问题中提到的方法是将文本文件放在项目中的某个位置,在“解决方案资源管理器”中选择它,按F4显示属性,然后将生成操作设置为嵌入的资源,并将复制到输出目录保留为不复制
这与添加到.csproj中相同:
<ItemGroup>
    <EmbeddedResource Include="Resources\TextFile.txt"/>
</ItemGroup>

那么你需要正确的 Assembly 实例或者一个 IFileProvider 来通过名称访问这些资源。

通过 Assembly:

typeof(Program).Assembly.GetManifestResourceNames()
typeof(Program).Assembly.GetManifestResourceStream(name)
typeof(Program).Assembly.GetManifestResourceInfo(name)

这些名称类似于类名,由点号分隔。如果您的项目是NamespaceName.ProjectName,资源文件位于Resources子文件夹中,名为TextFile.txt,则资源名称将是

NamespaceName.ProjectName.Resources.TextFile.txt

有一个重载版本的GetManifestResourceStream方法可以接受一个类型参数,你可以这样使用:

typeof(Program).Assembly.GetManifestResourceStream(
    typeof(Program),
    "Resources.TextFile.txt")

不要依赖默认的命名空间或项目输出文件名。这样做的缺点是它们似乎不能从观察窗口工作。您可能会收到一个异常。
System.ArgumentException "Cannot evaluate a security function."

在这种情况下,只需将代码编写到可以随意执行的地方 - 例如静态方法中。这样,代码将从您的程序集而不是调试器中运行。

并且通过 IFileProvider

dotnet add package Microsoft.Extensions.FileProviders.Embedded
using Microsoft.Extensions.FileProviders;
var fp = new EmbeddedFileProvider(typeof(Program).Assembly);
// get all resources as an enumerable
foreach (var fileInfo in fp.GetDirectoryContents(""))
    Console.WriteLine($"Name: {fileInfo.Name}, Length: {fileInfo.Length}, ...");
// get a specific one by name
var stream = fp.GetFileInfo("Resources.TextFile.txt").CreateReadStream();

作为一个IFileProvider,您可以尝试从纯嵌入式资源托管.NET Core网站。

2

使用.ResX资源与将文本文件嵌入到程序集中略有不同。对于后者,您需要检查其属性并将其设置为EmbeddedResource(即,无需向ResX文件添加任何内容,只需将文本文件放入VS项目中)。要检索它,请使用以下代码:

Assembly.GetExecutingAssembly().GetManifestResourceStream(name);

要获取正确的name参数值,请调用GetManifestResourceNames()并检查结果。

嗯...所以我使用了Assembly.GetExecutingAssembly().GetManifestResourceStream("Explaination.txt");,而Explaination.txt在我的调试文件夹中,但是这行代码似乎没有任何作用。你有什么想法吗? - windowsgm
请注意,我只想在记事本中打开文本文件。 - windowsgm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接