code

임베디드 리소스 텍스트 파일 읽는 방법

codestyles 2020. 10. 2. 22:21
반응형

임베디드 리소스 텍스트 파일 읽는 방법


포함 된 리소스 (텍스트 파일)를 어떻게 읽고 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();
}

Assembly.GetManifestResourceStream방법을 사용할 수 있습니다 .

  1. 다음 용도를 추가하십시오.

    using System.IO;
    using System.Reflection;
    
  2. 관련 파일의 속성 설정 : 값이있는
    매개 변수Build ActionEmbedded 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();
}

resourceName에 포함 된 리소스 중 하나의 이름입니다 assembly. 라는 이름의 텍스트 파일을 포함 할 경우 예를 들어, "MyFile.txt"기본 네임 스페이스 프로젝트의 루트에 위치 "MyCompany.MyProduct"하고 resourceName있습니다 "MyCompany.MyProduct.MyFile.txt". Assembly.GetManifestResourceNamesMethod를 사용하여 어셈블리의 모든 리소스 목록을 가져올 수 있습니다 .


resourceName파일 이름에서만 (네임 스페이스 항목을 전달하여) 가져 오는 것에 대해 생각할 필요가 없습니다 .

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

별도의 두 가지 방법을 사용하여 파일을 리소스로 추가 할 수 있습니다.

파일에 액세스하는 데 필요한 C # 코드 는 처음에 파일을 추가하는 데 사용 된 방법에 따라 다릅니다.

방법 1 : 기존 파일 추가, 속성 설정 Embedded Resource

프로젝트에 파일을 추가 한 다음 유형을 Embedded Resource.

참고 :이 방법을 사용하여 파일을 추가 하면를 사용하여 파일 GetManifestResourceStream에 액세스 할 수 있습니다 ( @dtb의 답변 참조 ).

여기에 이미지 설명 입력

방법 2 : 파일 추가 Resources.resx

위 열고 Resources.resx, 설정을 파일을 추가 드롭 다운 상자를 사용하여 파일을 Access Modifierpublic.

참고 :이 방법을 사용하여 파일을 추가 하면를 사용하여 파일 Properties.Resources에 액세스 할 수 있습니다 ( @Night Walker의 답변 참조 ).

여기에 이미지 설명 입력


기본적으로 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!");
   }

Visual Studio에서는 프로젝트 속성의 리소스 탭 (이 예에서는 "분석")을 통해 파일 리소스에 대한 액세스를 직접 포함 할 수 있습니다. Visual Studio 스크린 샷-리소스 탭

결과 파일은 다음을 통해 바이트 배열로 액세스 할 수 있습니다.

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

스트림으로 필요하면 ( https://stackoverflow.com/a/4736185/432976에서 )

Stream stream = new MemoryStream(jsonSecrets)

리소스에 파일을 추가 할 때 다음과 같이 만들 수있는 것보다 해당 액세스 수정자를 공용으로 선택해야합니다.

byte[] clistAsByteArray = Properties.Resources.CLIST01;

CLIST01은 임베드 된 파일의 이름입니다.

실제로 resources.Designer.cs로 이동하여 getter의 이름이 무엇인지 확인할 수 있습니다.


나는 그것이 오래된 스레드라는 것을 알고 있지만 이것이 나를 위해 일한 것입니다.

  1. 프로젝트 리소스에 텍스트 파일 추가
  2. Andrew Hill이 위에서 보여준 것처럼 access modifier를 public으로 설정합니다.
  3. 다음과 같은 텍스트를 읽으십시오.

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

리소스에 추가 한 텍스트 : 'SomeText.txt'


추가 예 : Testfile.sql 프로젝트 메뉴-> 속성-> 리소스-> 기존 파일 추가

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

여기에 이미지 설명 입력


이 단순화 된 버전의 @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();
    }
}

방금 배운 것은 파일에 "."가 있으면 안된다는 것입니다. (점) 파일 이름에.

ㅏ "."  파일 이름은 좋지 않습니다.

Templates.plainEmailBodyTemplate-en.txt-> 작동 !!!
Templates.plainEmailBodyTemplate.en.txt-> GetManifestResourceStream ()을 통해 작동하지 않습니다.

아마도 프레임 워크가 네임 스페이스 대 파일 이름을 혼동하기 때문일 것입니다.


모든 힘을 합쳐서이 도우미 클래스를 사용하여 어셈블리와 네임 스페이스에서 리소스를 일반적인 방식으로 읽습니다.

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

포함 된 리소스 텍스트 파일 사용을 읽었습니다.

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

나는 이것이 오래 되었다는 것을 알고 있지만 NETMF (.Net MicroFramework)에 대해 지적하고 싶었습니다. 쉽게 할 수 있습니다.

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

이후 NETMF는 없습니다GetManifestResourceStream


여기에 게시 된 모든 솔루션을 읽은 후. 이것이 내가 해결 한 방법입니다.

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

문자열에 항상 네임 스페이스와 폴더를 포함해야한다는 점에 짜증이났습니다. 임베디드 리소스에 대한 액세스를 단순화하고 싶었습니다. 이것이 제가이 작은 수업을 작성한 이유입니다. 자유롭게 사용하고 개선하십시오!

용법:

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

}

대답은 매우 간단합니다. resources.resx에서 직접 파일을 추가 한 경우 간단하게 수행하십시오.

string textInResourceFile = fileNameSpace.Properties.Resources.fileName;

해당 코드 줄을 사용하여 파일의 텍스트를 파일에서 직접 읽어 문자열 변수에 넣습니다.


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

일부 VS .NET 프로젝트 유형은 .NET (.resx) 파일을 자동 생성하지 않습니다. 다음 단계는 프로젝트에 리소스 파일을 추가합니다.

  1. 프로젝트 노드를 마우스 오른쪽 버튼으로 클릭하고 추가 / 새 항목을 선택하고 리소스 파일로 스크롤합니다. 이름 상자에서 적절한 이름 (예 : Resources)을 선택하고 추가 버튼을 클릭합니다.
  2. 리소스 파일 Resources.resx가 프로젝트에 추가되고 솔루션 탐색기에서 노드로 표시 될 수 있습니다.
  3. 실제로 두 개의 파일이 생성되고 자동 생성 된 C # 클래스 Resources.Designer.cs도 있습니다. 편집하지 마십시오. VS에서 관리합니다. 파일에는 Resources.

이제 텍스트 파일을 리소스 (예 : xml 파일)로 추가 할 수 있습니다.

  1. Resources.resx를 두 번 클릭합니다. 리소스 추가> 기존 파일 추가를 선택하고 포함 할 파일로 스크롤합니다. Access Modify에 대해 기본값 내부를 그대로 둡니다.
  2. 아이콘은 새 리소스 항목을 나타냅니다. 선택하면 속성 창에 속성이 표시됩니다. xml 파일의 경우 인코딩 속성에서 기본 로컬 코드 페이지 대신 유니 코드 (UTF-8) – 코드 페이지 65001을 선택합니다. 다른 텍스트 파일의 경우이 파일의 올바른 인코딩 (예 : 코드 페이지 1252)을 선택하십시오.
  3. xml 파일과 같은 텍스트 파일의 경우 클래스 Resources에는 string포함 된 파일의 이름을 따서 명명 된 유형의 속성이 있습니다. 파일 이름이 예를 들어 RibbonManifest.xml 인 경우 속성의 이름은 RibbonManifest. 코드 파일 Resources.Designer.cs에서 정확한 이름을 찾을 수 있습니다.
  4. 다른 문자열 속성과 마찬가지로 문자열 속성을 사용합니다 (예 : string xml = Resources.RibbonManifest. 일반적인 형식은 ResourceFileName.IncludedTextFileName. ResourceManager.GetString문자열 속성의 get-function이 이미 수행 했으므로 사용하지 마십시오 .

Form Load Event에서 Embedded TXT FILE을 읽습니다.

변수를 동적으로 설정합니다.

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

Try Catch를 호출하십시오.

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이 작업을 수행합니다. 전구를 클릭하여 CodeBlock을 자동 생성합니다.

생성 된 코드 블록 안에 다음을 넣으십시오.

자원 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 파일을 결합하고 단일 서식있는 텍스트 상자 안에 포함 된 데이터를 읽는 방법입니다. 이 코드 샘플에서 원하는 효과였습니다.

참고 URL : https://stackoverflow.com/questions/3314140/how-to-read-embedded-resource-text-file

반응형