如何使用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();
}

当前回答

如SonarCloud所示,更好的做法是:

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

        // Non-compliant
        Assembly assembly = Assembly.GetExecutingAssembly();
        Console.WriteLine("Assembly name: {0}", assem.FullName);
    }
}

其他回答

我很恼火,你必须在字符串中始终包含名称空间和文件夹。我想简化对嵌入式资源的访问。这就是我写这个小课堂的原因。欢迎使用和改进!

用法:

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)));

}

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

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

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

例如,从我发布的页面:

注:需要添加使用System.Reflection;让它发挥作用

   Assembly _assembly;
   StreamReader _textStreamReader;

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

对于使用VB.Net的用户

Imports System.IO
Imports System.Reflection

Dim reader As StreamReader
Dim 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()

or

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

or

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

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

    /// <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);
});