关于.NET:如何读取嵌入的资源文本文件

How to read embedded resource text file

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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();
}

您可以使用Assembly.GetManifestResourceStream方法:

  • 添加以下用法

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

  • 使用以下代码

  • 1
    2
    3
    4
    5
    6
    7
    8
    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();
    }

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

    只从文件名中获取resourceName是一种不费吹灰之力的聪明方法(通过名称空间的东西):

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


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

    访问文件所需的C代码是不同的,这取决于最初添加文件所用的方法。

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

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

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

    enter image description here

    方法二:向Resources.resx添加文件

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

    注意:如果使用此方法添加文件,则可以使用Properties.Resources访问它(请参见@night walker的应答)。

    enter image description here


    查看此页:http://support.microsoft.com/kb/319292

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

    例如,从我发布的页面:

    注:需要增加using System.Reflection;才能起作用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
       Assembly _assembly;
       StreamReader _textStreamReader;

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


    在Visual Studio中,可以通过项目属性的"资源"选项卡(本例中的"分析")直接嵌入对文件资源的访问。visual studio screen shot - Resources tab

    然后可以通过以下方式以字节数组的形式访问结果文件:

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

    如果您需要它作为流,那么(来自https://stackoverflow.com/a/4736185/432976)

    1
    Stream stream = new MemoryStream(jsonSecrets)


    将文件添加到资源中时,应将其访问修饰符选择为"公共",而不能进行如下操作。

    1
    byte[] clistAsByteArray = Properties.Resources.CLIST01;

    clist01是嵌入文件的名称。

    实际上,您可以转到resources.designer.cs,查看getter的名称。


    我知道这是一条古老的线,但这对我很有用:

  • 将文本文件添加到项目资源
  • 将访问修饰符设置为public,如上面Andrew Hill所示。
  • 阅读文本如下:

    1
    2
    textBox1 = new TextBox();
    textBox1.Text = Properties.Resources.SomeText;
  • 我添加到资源中的文本:"sometext.txt"


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

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

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

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


    我刚才了解到,文件名中不允许有"."(点)。

    A

    templates.plainemailbodytemplate-en.txt->有效!!!!templates.plainemailbodytemplate.en.txt-->无法通过getmanifestresourcestream()工作

    可能是因为框架在名称空间和文件名之间混淆了…


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    public class ResourceReader
    {
        public static IEnumerable<string> FindEmbededResources<TAssembly>(Func<string, bool> predicate)
        {
            if (predicate == null) throw new ArgumentNullException(nameof(predicate));

            return
                GetEmbededResourceNames<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();
                }
            }
        }
    }


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        /// <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));
        }

    Sample:

    1
    2
    3
    4
    5
    6
    var template = GetLines(Properties.Resources.LasTemplate /* resource name */);

    template.ForEach(ln =>
    {
        Debug.WriteLine(ln);
    });


    您必须始终在字符串中包含名称空间和文件夹,这让我很恼火。我想简化对嵌入式资源的访问。这就是我为什么写这个小班的原因。随时使用和改进!

    用途:

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

    班级:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    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)));

    }


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    // 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"";      
    }

    我知道这很古老,但我只是想指出对于netmf(.net microframework),您可以很容易地做到:

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

    因为netmf没有GetManifestResourceStream


    答案很简单,如果直接从resources.resx添加文件,只需执行此操作。

    1
    string textInResourceFile = fileNameSpace.Properties.Resources.fileName;

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


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    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;
        }
    }


    在窗体加载事件中读取嵌入的TXT文件。动态设置变量。

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

    调用一个try-catch。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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.
    }

    为includeText()创建void,Visual Studio会为您执行此操作。单击灯泡以自动生成代码块。

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

    资源1

    1
    2
    3
    4
    5
    6
    7
    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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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

    1
    2
    3
    4
    5
    6
    7
    8
    var assembly = Assembly.GetExecutingAssembly();
    using (Stream stream = assembly.GetManifestResourceStream(file3))

    using (StreamReader reader = new StreamReader(stream))
    {
        string result3 = reader.ReadToEnd();
        richTextBox1.AppendText(result3);
    }

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    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文件组合在一个富文本框中并读取其嵌入数据的方法。这是我对这个代码示例所期望的效果。