如何读取嵌入的资源文本文件

如何使用StreamReader读取嵌入资源(文本文件)并将其作为字符串返回?我当前的脚本使用Windows表单和文本框,允许用户在未嵌入的文本文件中查找和替换文本。

private void button1_Click(object sender, EventArgs e){StringCollection strValuesToSearch = new StringCollection();strValuesToSearch.Add("Apple");string stringToReplace;stringToReplace = textBox1.Text;
StreamReader FileReader = new StreamReader(@"C:\MyFile.txt");string FileContents;FileContents = FileReader.ReadToEnd();FileReader.Close();foreach (string s in strValuesToSearch){if (FileContents.Contains(s))FileContents = FileContents.Replace(s, stringToReplace);}StreamWriter FileWriter = new StreamWriter(@"MyFile.txt");FileWriter.Write(FileContents);FileWriter.Close();}
758152 次浏览

基本上,您使用System.Reflection来获取对当前程序集的引用。然后,您使用GetManifestResourceStream()

例如,从我发布的页面:

说明:需要添加using System.Reflection;才能工作

   Assembly _assembly;StreamReader _textStreamReader;
try{_assembly = Assembly.GetExecutingAssembly();_textStreamReader = new StreamReader(_assembly.GetManifestResourceStream("MyNamespace.MyTextFile.txt"));}catch{MessageBox.Show("Error accessing resources!");}

您可以使用#0方法

  1. 添加以下用法

     using System.IO;using System.Reflection;
  2. 设置相关文件的属性:
    参数Build Action,值Embedded Resource

  3. 使用以下代码

     var assembly = Assembly.GetExecutingAssembly();var resourceName = "MyCompany.MyProduct.MyFile.txt";
    using (Stream stream = assembly.GetManifestResourceStream(resourceName))using (StreamReader reader = new StreamReader(stream)){string result = reader.ReadToEnd();}

    resourceNameassembly中嵌入的资源之一的名称。例如,如果您嵌入了一个名为"MyFile.txt"的文本文件,该文件放置在具有默认命名空间"MyCompany.MyProduct"的项目根目录中,那么resourceName就是"MyCompany.MyProduct.MyFile.txt"。您可以使用#0方法获取程序集中所有资源的列表。


一个没有头脑的精明只从文件名中获取resourceName(通过名称空间的东西):

string resourceName = assembly.GetManifestResourceNames().Single(str => str.EndsWith("YourFileName.txt"));

一个完整的例子:

public string ReadResource(string name){// Determine pathvar assembly = Assembly.GetExecutingAssembly();string resourcePath = name;// Format: "{Namespace}.{Folder}.{filename}.{Extension}"if (!name.StartsWith(nameof(SignificantDrawerCompiler))){resourcePath = assembly.GetManifestResourceNames().Single(str => str.EndsWith(name));}
using (Stream stream = assembly.GetManifestResourceStream(resourcePath))using (StreamReader reader = new StreamReader(stream)){return reader.ReadToEnd();}}

或者作为异步扩展方法:

internal static class AssemblyExtensions{public static async Task<string> ReadResourceAsync(this Assembly assembly, string name){// Determine pathstring resourcePath = name;// Format: "{Namespace}.{Folder}.{filename}.{Extension}"if (!name.StartsWith(nameof(SignificantDrawerCompiler))){resourcePath = assembly.GetManifestResourceNames().Single(str => str.EndsWith(name));}
using Stream stream = assembly.GetManifestResourceStream(resourcePath)!;using StreamReader reader = new(stream);return await reader.ReadToEndAsync();}}
// Usagestring resourceText = await Assembly.GetExecutingAssembly().ReadResourceAsync("myResourceName");

当您将文件添加到资源时,您应该将其访问修饰符选择为公共,而不是像下面这样。

byte[] clistAsByteArray = Properties.Resources.CLIST01;

CLIST01是嵌入文件的名称。

实际上你可以去resources.Designer.cs看看吸气剂的名字是什么。

您也可以使用@dtb答案的简化版本:

public string GetEmbeddedResource(string ns, string res){using (var reader = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(string.Format("{0}.{1}", ns, res)))){return reader.ReadToEnd();}}

在Visual Studio中,您可以通过项目属性的资源选项卡(本例中为“分析”)直接嵌入对文件资源的访问。视觉工作室截图-资源选项卡

然后可以通过以下方式将生成的文件作为字节数组访问

byte[] jsonSecrets = GoogleAnalyticsExtractor.Properties.Resources.client_secrets_reporter;

如果你需要它作为一个流,那么(从https://stackoverflow.com/a/4736185/432976

Stream stream = new MemoryStream(jsonSecrets)

我读了一个嵌入资源文本文件使用:

    /// <summary>/// Converts to generic list a byte array/// </summary>/// <param name="content">byte array (embedded resource)</param>/// <returns>generic list of strings</returns>private List<string> GetLines(byte[] content){string s = Encoding.Default.GetString(content, 0, content.Length - 1);return new List<string>(s.Split(new[] { Environment.NewLine }, StringSplitOptions.None));}

样本:

var template = GetLines(Properties.Resources.LasTemplate /* resource name */);
template.ForEach(ln =>{Debug.WriteLine(ln);});

我知道这是一个古老的线程,但这对我来说是有效的:

  1. 将文本文件添加到项目资源
  2. 将访问修饰符设置为public,如Andrew Hill所示
  3. 阅读这样的文本:

    textBox1 = new TextBox();textBox1.Text = Properties.Resources.SomeText;

The text that I added to the resources: 'SomeText.txt'

您可以使用两种不同的方法将文件添加为资源。

访问文件所需的C#代码不同,具体取决于首先用于添加文件的方法。

方法1:添加现有文件,将属性设置为Embedded Resource

将文件添加到您的项目中,然后将类型设置为Embedded Resource

注意:如果使用此方法添加文件,则可以使用GetManifestResourceStream访问它(请参阅@dtb的答案

输入图片描述

方法2:将文件添加到Resources.resx

打开Resources.resx文件,使用下拉框添加文件,将Access Modifier设置为public

注意:如果您使用此方法添加文件,您可以使用Properties.Resources访问它(请参阅@Night Walker的答案

输入图片描述

我刚才学到的是,您的文件名中不允许有“.”(点)。

A

Templates.plainEmailBodyTemplate-en.txt-->有用!!!
Templates.plainEmailBodyTemplate.en.txt-->无法通过GetManifestResourceStream()

可能是因为框架混淆了命名空间与文件名…

我知道这是旧的,但我只是想指出NETMF(. Net MicroFramework),您可以轻松做到这一点:

string response = Resources.GetString(Resources.StringResources.MyFileName);

因为NETMF没有GetManifestResourceStream

我很生气你必须总是在字符串中包含命名空间和文件夹。我想简化对嵌入式资源的访问。这就是我写这个小类的原因。请随时使用和改进!

用法:

using(Stream stream = EmbeddedResources.ExecutingResources.GetStream("filename.txt")){//...}

班级:

public class EmbeddedResources{private static readonly Lazy<EmbeddedResources> _callingResources = new Lazy<EmbeddedResources>(() => new EmbeddedResources(Assembly.GetCallingAssembly()));
private static readonly Lazy<EmbeddedResources> _entryResources = new Lazy<EmbeddedResources>(() => new EmbeddedResources(Assembly.GetEntryAssembly()));
private static readonly Lazy<EmbeddedResources> _executingResources = new Lazy<EmbeddedResources>(() => new EmbeddedResources(Assembly.GetExecutingAssembly()));
private readonly Assembly _assembly;
private readonly string[] _resources;
public EmbeddedResources(Assembly assembly){_assembly = assembly;_resources = assembly.GetManifestResourceNames();}
public static EmbeddedResources CallingResources => _callingResources.Value;
public static EmbeddedResources EntryResources => _entryResources.Value;
public static EmbeddedResources ExecutingResources => _executingResources.Value;
public Stream GetStream(string resName) => _assembly.GetManifestResourceStream(_resources.Single(s => s.Contains(resName)));
}

读取表单加载事件上的嵌入式TXT文件。

动态设置变量。

string f1 = "AppName.File1.Ext";string f2 = "AppName.File2.Ext";string f3 = "AppName.File3.Ext";

打电话给尝试捕获。

try{IncludeText(f1,f2,f3);/// Pass the Resources Dynamically/// through the call stack.}
catch (Exception Ex){MessageBox.Show(Ex.Message);/// Error for if the Stream is Null.}

为包含文本()创建空,Visual Studio为您执行此操作。单击灯泡以自动生成代码块。

将以下内容放入生成的代码块中

资源1

var assembly = Assembly.GetExecutingAssembly();using (Stream stream = assembly.GetManifestResourceStream(file1))using (StreamReader reader = new StreamReader(stream)){string result1 = reader.ReadToEnd();richTextBox1.AppendText(result1 + Environment.NewLine + Environment.NewLine );}

资源2

var assembly = Assembly.GetExecutingAssembly();using (Stream stream = assembly.GetManifestResourceStream(file2))using (StreamReader reader = new StreamReader(stream)){string result2 = reader.ReadToEnd();richTextBox1.AppendText(result2 + Environment.NewLine +Environment.NewLine );}

资源3

var assembly = Assembly.GetExecutingAssembly();using (Stream stream = assembly.GetManifestResourceStream(file3))
using (StreamReader reader = new StreamReader(stream)){string result3 = reader.ReadToEnd();richTextBox1.AppendText(result3);}

如果您想将返回的变量发送到其他地方,只需调用另一个函数并…

using (StreamReader reader = new StreamReader(stream)){string result3 = reader.ReadToEnd();///richTextBox1.AppendText(result3);string extVar = result3;
/// another try catch here.
try {
SendVariableToLocation(extVar){//// Put Code Here.}
}
catch (Exception ex){Messagebox.Show(ex.Message);}
}

这实现了这一点,一个方法来组合多个txt文件,并读取其嵌入的数据,在一个单一的丰富的输入框.这是我想要的效果与此代码示例。

通过结合您的所有功能,我使用这个助手类以通用方式从任何程序集和任何命名空间读取资源。

public class ResourceReader{public static IEnumerable<string> FindEmbededResources<TAssembly>(Func<string, bool> predicate){if (predicate == null) throw new ArgumentNullException(nameof(predicate));
returnGetEmbededResourceNames<TAssembly>().Where(predicate).Select(name => ReadEmbededResource(typeof(TAssembly), name)).Where(x => !string.IsNullOrEmpty(x));}
public static IEnumerable<string> GetEmbededResourceNames<TAssembly>(){var assembly = Assembly.GetAssembly(typeof(TAssembly));return assembly.GetManifestResourceNames();}
public static string ReadEmbededResource<TAssembly, TNamespace>(string name){if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name));return ReadEmbededResource(typeof(TAssembly), typeof(TNamespace), name);}
public static string ReadEmbededResource(Type assemblyType, Type namespaceType, string name){if (assemblyType == null) throw new ArgumentNullException(nameof(assemblyType));if (namespaceType == null) throw new ArgumentNullException(nameof(namespaceType));if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name));
return ReadEmbededResource(assemblyType, $"{namespaceType.Namespace}.{name}");}
public static string ReadEmbededResource(Type assemblyType, string name){if (assemblyType == null) throw new ArgumentNullException(nameof(assemblyType));if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name));
var assembly = Assembly.GetAssembly(assemblyType);using (var resourceStream = assembly.GetManifestResourceStream(name)){if (resourceStream == null) return null;using (var streamReader = new StreamReader(resourceStream)){return streamReader.ReadToEnd();}}}}

添加例如Testfile.sql项目菜单->属性->资源->添加现有文件

    string queryFromResourceFile = Properties.Resources.Testfile.ToString();

在此处输入图片描述

在阅读了这里发布的所有解决方案之后。我是这样解决的:

// How to embedded a "Text file" inside of a C# project//   and read it as a resource from c# code://// (1) Add Text File to Project.  example: 'myfile.txt'//// (2) Change Text File Properties://      Build-action: EmbeddedResource//      Logical-name: myfile.txt//          (note only 1 dot permitted in filename)//// (3) from c# get the string for the entire embedded file as follows:////     string myfile = GetEmbeddedResourceFile("myfile.txt");
public static string GetEmbeddedResourceFile(string filename) {var a = System.Reflection.Assembly.GetExecutingAssembly();using (var s = a.GetManifestResourceStream(filename))using (var r = new System.IO.StreamReader(s)){string result = r.ReadToEnd();return result;}return "";}
public class AssemblyTextFileReader{private readonly Assembly _assembly;
public AssemblyTextFileReader(Assembly assembly){_assembly = assembly ?? throw new ArgumentNullException(nameof(assembly));}
public async Task<string> ReadFileAsync(string fileName){var resourceName = _assembly.GetManifestResourceName(fileName);
using (var stream = _assembly.GetManifestResourceStream(resourceName)){using (var reader = new StreamReader(stream)){return await reader.ReadToEndAsync();}}}}
public static class AssemblyExtensions{public static string GetManifestResourceName(this Assembly assembly, string fileName){string name = assembly.GetManifestResourceNames().SingleOrDefault(n => n.EndsWith(fileName, StringComparison.InvariantCultureIgnoreCase));
if (string.IsNullOrEmpty(name)){throw new FileNotFoundException($"Embedded file '{fileName}' could not be found in assembly '{assembly.FullName}'.", fileName);}
return name;}}
// To use the code above:var reader = new AssemblyTextFileReader(assembly);
string text = await reader.ReadFileAsync(@"MyFile.txt");

答案很简单,如果您直接从resources.resx.添加文件,只需这样做

string textInResourceFile = fileNameSpace.Properties.Resources.fileName;

使用该行代码,可以直接从文件中读取文件中的文本并将其放入字符串变量中。

某些VS. NET项目类型不会自动生成. NET(. resx)文件。以下步骤将资源文件添加到您的项目中:

  1. 右键单击项目节点并选择添加/新建项目,滚动到资源文件。在名称框中选择适当的名称,例如资源,然后单击按钮添加。
  2. 资源文件Resources.resx被添加到项目中,可以看作是解决方案资源管理器中的一个节点。
  3. 实际上,创建了两个文件,还有一个自动生成的C#类Resources.Designer.cs.不要编辑它,它由VS维护。该文件包含一个名为Resources的类。

现在您可以添加文本文件作为资源,例如xml文件:

  1. 双击Resources.resx.选择添加资源>添加现有文件并滚动到要包含的文件。保留Access修改的默认值内部。
  2. 图标表示新的资源项。如果选中此项,属性窗格将显示其属性。对于xml文件,请在属性编码下选择Unicode(UTF-8)-代码页65001,而不是默认的本地代码页。对于其他文本文件,请选择此文件的正确编码,例如代码页1252。
  3. 对于像xml文件这样的文本文件,类Resources有一个类型为string的属性,它是以包含的文件命名的。如果文件名是RibbonManifest.xml,那么该属性的名称应该是RibbonManifest。您可以在代码文件中找到确切的名称Resources.Designer.cs.
  4. 像使用任何其他字符串属性一样使用字符串属性,例如:string xml = Resources.RibbonManifest。一般形式是ResourceFileName.IncludedTextFileName。不要使用ResourceManager.GetString,因为字符串属性的get函数已经这样做了。

这是一个类,您可能会发现从当前Assembly读取嵌入式资源文件非常方便:

using System.IO;using System.Linq;using System.Text;using System.Reflection;
public static class EmbeddedResourceUtils{public static string ReadFromResourceFile(string endingFileName){var assembly = Assembly.GetExecutingAssembly();var manifestResourceNames = assembly.GetManifestResourceNames();
foreach (var resourceName in manifestResourceNames){var fileNameFromResourceName = _GetFileNameFromResourceName(resourceName);if (!fileNameFromResourceName.EndsWith(endingFileName)){continue;}
using (var manifestResourceStream = assembly.GetManifestResourceStream(resourceName)){if (manifestResourceStream == null){continue;}
using (var streamReader = new StreamReader(manifestResourceStream)){return streamReader.ReadToEnd();}}}
return null;}    
// https://stackoverflow.com/a/32176198/3764804private static string _GetFileNameFromResourceName(string resourceName){var stringBuilder = new StringBuilder();var escapeDot = false;var haveExtension = false;
for (var resourceNameIndex = resourceName.Length - 1;resourceNameIndex >= 0;resourceNameIndex--){if (resourceName[resourceNameIndex] == '_'){escapeDot = true;continue;}
if (resourceName[resourceNameIndex] == '.'){if (!escapeDot){if (haveExtension){stringBuilder.Append('\\');continue;}
haveExtension = true;}}else{escapeDot = false;}
stringBuilder.Append(resourceName[resourceNameIndex]);}
var fileName = Path.GetDirectoryName(stringBuilder.ToString());return fileName == null ? null : new string(fileName.Reverse().ToArray());}}

对于所有快速想要在winform中硬编码文件文本的人;

  1. 在解决方案资源管理器>资源>添加文件中右键单击应用程序。
  2. 单击它,并在属性选项卡中将“FileType”设置为“Text”。
  3. 在您的程序中,只需执行Resources.<name of resource>.toString();来读取文件。

我不会推荐这作为最佳实践或任何东西,但它可以快速工作并做它需要做的事情。

对于使用VB. Net的用户

Imports System.IOImports System.Reflection
Dim reader As StreamReaderDim ass As Assembly = Assembly.GetExecutingAssembly()Dim sFileName = "MyApplicationName.JavaScript.js"Dim reader = New StreamReader(ass.GetManifestResourceStream(sFileName))Dim sScriptText = reader.ReadToEnd()reader.Close()

其中MyApplicationName是我的应用程序的命名空间。它不是程序集名称。此名称在项目的属性(应用程序选项卡)中定义。

如果没有找到正确的资源名称,可以使用GetManifestResourceNames()函数

Dim resourceName() As String = ass.GetManifestResourceNames()

Dim sName As String= ass.GetManifestResourceNames().Single(Function(x) x.EndsWith("JavaScript.js"))

Dim sNameList= ass.GetManifestResourceNames().Where(Function(x As String) x.EndsWith(".js"))

我想将嵌入的资源作为字节数组读取(不假设任何特定编码),最终我使用了MemoryStream,这使得它非常简单:

using var resStream = assembly.GetManifestResourceStream(GetType(), "file.txt");var ms = new MemoryStream();await resStream .CopyToAsync(ms);var bytes = ms.ToArray();

正如SonarCloud所指出的那样:

public class Example{public static void Main(){// Compliant: type of the current classAssembly assembly = typeof(Example).Assembly;Console.WriteLine("Assembly name: {0}", assem.FullName);
// Non-compliantAssembly assembly = Assembly.GetExecutingAssembly();Console.WriteLine("Assembly name: {0}", assem.FullName);}}