วิธีอ่านไฟล์ข้อความของทรัพยากรที่ฝังตัว


694

ฉันจะอ่านทรัพยากรที่ฝังตัว (ไฟล์ข้อความ) โดยใช้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();
}

คำตอบ:


1197

คุณสามารถใช้Assembly.GetManifestResourceStreamวิธีการ :

  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"ที่วางอยู่ในรากของโครงการที่มี namespace เริ่มต้น"MyCompany.MyProduct"แล้วคือresourceName "MyCompany.MyProduct.MyFile.txt"คุณจะได้รับรายการของทรัพยากรทั้งหมดในการชุมนุมโดยใช้วิธีการAssembly.GetManifestResourceNames


ไม่มีเกมง่ายๆที่จะได้รับresourceNameจากชื่อไฟล์เท่านั้น (โดยผ่านรายการเนมสเปซ):

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

ตัวอย่างที่สมบูรณ์:

public string ReadResource(string name)
{
    // Determine path
    var 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();
    }
}

5
@ Me.Close: ดูที่Environment.SpecialFolderโฟลเดอร์เดสก์ทอป คุณต้องจำไว้ว่าทรัพยากรจะ namespaced file1.txtขึ้นอยู่กับเส้นทางของมันภายในโครงการเพื่อให้ชื่อของมันอาจจะไม่ได้เป็นเพียงแค่
adrianbanks

15
อาร์กิวเมนต์สำหรับGetManifestResourceStreamความต้องการพา ธ ตามที่ @adrian บ่งชี้ ถ้ามันจะช่วยให้ทุกคนเส้นทางที่เป็นเหมือนการแสดงสิ่งที่ @SimpleCoder MyNamespace.Filename.Extในตัวอย่าง: ก่อนหน้านี้ฉันได้ลองแล้วMyNamespace.Resources.Filename.Extแต่ผลลัพธ์นั้นเป็นโมฆะ
JYelton

61
หากคุณมีทรัพยากรของคุณไม่ได้อยู่ในรูทโปรเจ็กต์โดยตรง แต่ในบางโฟลเดอร์ย่อยอย่าลืมใส่ชื่อโฟลเดอร์นี้ใน resourceName ด้วย (เช่น "MyProjectNameSpace.MyProjectSubFolder.FileName.FileExtention")
Sasha

19
คุ้มค่าที่จะกล่าวว่าทรัพยากร "Build Action" จะต้องมีการตั้งค่าเป็น "ทรัพยากรที่ฝังตัว"
Illidan

7
จุดสำคัญหนึ่งที่ไม่ครอบคลุมในที่นี้ หากคุณบันทึกไฟล์ของคุณเป็นประเภทการเข้ารหัสทางเลือกเพื่อรับมือกับอักขระแปลก ๆ (ในกรณีของฉัน UTF8) คุณอาจได้รับไฟล์เปล่ากลับมาเมื่อคุณอ่านกระแสข้อมูล แก้ไขสิ่งนี้โดยการระบุประเภทการเข้ารหัสในตัวสร้างของตัวอ่านกระแส:using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
Kinetic

140

คุณสามารถเพิ่มไฟล์เป็นทรัพยากรโดยใช้สองวิธีแยกกัน

รหัส C # ที่จำเป็นในการเข้าถึงไฟล์นั้นแตกต่างกันไปขึ้นอยู่กับวิธีการที่ใช้ในการเพิ่มไฟล์ตั้งแต่แรก

วิธีที่ 1: เพิ่มไฟล์ที่มีอยู่ตั้งค่าคุณสมบัติเป็น Embedded Resource

Embedded Resourceเพิ่มไฟล์ไปยังโครงการของคุณแล้วตั้งคนประเภทที่จะ

หมายเหตุ: หากคุณเพิ่มไฟล์โดยใช้วิธีนี้คุณสามารถใช้GetManifestResourceStreamเพื่อเข้าถึง (ดูคำตอบจาก @dtb )

ป้อนคำอธิบายรูปภาพที่นี่

วิธีที่ 2: เพิ่มไฟล์ลงใน Resources.resx

เปิดResources.resxไฟล์ที่ใช้กล่องแบบเลื่อนลงเพื่อเพิ่มไฟล์ชุดที่จะAccess Modifierpublic

หมายเหตุ: หากคุณเพิ่มไฟล์โดยใช้วิธีนี้คุณสามารถใช้Properties.Resourcesเพื่อเข้าถึงไฟล์ได้ (ดูคำตอบจาก @Night Walker )

ป้อนคำอธิบายรูปภาพที่นี่


5
วิธีที่สามคือการเพิ่มไฟล์ลงในโครงการจากนั้นตั้งค่า "คัดลอกไปยังไดเรกทอรีออก" เป็น "จริง" ในการคอมไพล์ไฟล์จะถูกคัดลอกไปยังเอาต์พุต dir และคุณสามารถอ่านไฟล์โดยใช้วิธีการปกติ ตัวอย่าง: ในแอพ WPF เมื่อคุณต้องการแสดงภาพ
Contango

ดังนั้นการตั้งค่าการดำเนินการสร้างเพื่อResourceทำอะไรที่ช่วยให้คุณอ่านรายการเป็นทรัพยากรได้หรือไม่ คุณต้องใช้EmbeddedResourceหรือเพิ่มResources.resxไฟล์?
Maslow

3
@Maslow การตั้งค่าการดำเนินการสร้างเป็น 'ทรัพยากร' สร้างทรัพยากรที่เชื่อมโยงในขณะที่การตั้งค่าการดำเนินการสร้างเป็น 'ทรัพยากรฝังตัว' รวบรวมทรัพยากรในการชุมนุมออก คำว่า 'ทรัพยากรที่เชื่อมโยง' เป็นคำแฟนซีสำหรับ 'คัดลอกไฟล์ลงในไดเรกทอรีผลลัพธ์เมื่อรวบรวม' (จากนั้นคุณสามารถอ่านไฟล์ที่รันไทม์โดยใช้วิธีการปกติ) สำหรับข้อมูลเพิ่มเติมเกี่ยวกับความแตกต่างระหว่างทั้งสองประเภทที่เห็นการเพิ่มและแก้ไขทรัพยากร (Visual C #) ที่msdn.microsoft.com/en-us/library/7k989cfy(v=vs.90).aspx
Contango

หากคุณต้องการที่จะใช้ทรัพยากรด้วยวิธีนี้ แต่แบบไดนามิกเพียงแทนนี้: เขียนนี้:Properties.Resources.Your_resource_name Properties.Resources.ResourceManager.GetObject("Your_resource_name")
Lkor

86

โดยทั่วไปคุณใช้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!");
   }

32
+1 สำหรับการรวมnamespaceเป็นส่วนหนึ่งของชื่อทรัพยากร
Kirk Broadhurst

41
var auxList= System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames(); วิธีนี้อาจมีประโยชน์มากเมื่อคุณต้องการเรียนรู้ชื่อทรัพยากรที่แน่นอน (นำมาจากคำถามstackoverflow.com/questions/27757/… )
Oscar Foley

69

ใน Visual Studio คุณสามารถฝังการเข้าถึงทรัพยากรไฟล์โดยตรงผ่านแท็บทรัพยากรของคุณสมบัติโครงการ ("Analytics" ในตัวอย่างนี้) visual studio screen shot - แท็บทรัพยากร

ไฟล์ผลลัพธ์สามารถเข้าถึงได้เป็นอาร์เรย์ไบต์โดย

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

หากคุณต้องการใช้เป็นสตรีมแล้ว (จากhttps://stackoverflow.com/a/4736185/432976 )

Stream stream = new MemoryStream(jsonSecrets)

11
คุณยังสามารถใช้สิ่งนี้กับไฟล์ข้อความซึ่งในกรณีนี้คุณจะมี: string jsonSecrets = YourNameSpace.Properties.Resources.YourFileName;
ouflak

30

เมื่อคุณเพิ่มไฟล์ลงในแหล่งข้อมูลคุณควรเลือกตัวดัดแปลงการเข้าถึงเป็นสาธารณะมากกว่าที่คุณสามารถทำสิ่งต่อไปนี้

byte[] clistAsByteArray = Properties.Resources.CLIST01;

CLIST01 เป็นชื่อของไฟล์ฝังตัว

ที่จริงคุณสามารถไปที่ resources.Designer.cs และดูว่าชื่อของ getter คืออะไร


5
คุณช่วยอธิบายเพิ่มเติมได้ไหม? เมื่อ i คลิกขวา -> คุณสมบัติบนไฟล์ในโซลูชัน explorer จากนั้นตั้งActionเป็นIncorporated ressourceฉันไม่มีAccess Modifiersฟิลด์ใด ๆในแผงคุณสมบัติ นอกจากนี้ฉันไม่ได้Propersites.Resourcesเรียนฉันได้รับThe name 'Properties' does not exist in the current contextข้อผิดพลาดเมื่อรวบรวมรหัสของคุณ
Suzanne Dupéron

2
วิธีนี้จะใช้งานได้หากคุณฝังไฟล์ไว้Resources.resxดูคำตอบของฉันเกี่ยวกับวิธีการต่าง ๆ เพื่อฝังไฟล์ลงในโครงการ
Contango

13

การเพิ่มเช่นเมนูโครงการ Testfile.sql -> คุณสมบัติ -> ทรัพยากร -> เพิ่มไฟล์ที่มีอยู่

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

ป้อนคำอธิบายรูปภาพที่นี่


2
มันจะกลับไบต์ [] สำหรับไฟล์ข้อความใช้ `Encoding.UTF8.GetString (Properties.Resources.Testfile)`
MikeTheCoder

12

ฉันรู้ว่ามันเป็นเธรดเก่า แต่นี่คือสิ่งที่ได้ผลสำหรับฉัน:

  1. เพิ่มไฟล์ข้อความลงในทรัพยากรโครงการ
  2. ตั้งค่าตัวดัดแปลงการเข้าถึงเป็นสาธารณะตามที่แสดงข้างต้นโดย Andrew Hill
  3. อ่านข้อความเช่นนี้:

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

ข้อความที่ฉันเพิ่มลงในทรัพยากร: 'SomeText.txt'


8

นอกจากนี้คุณยังสามารถใช้คำตอบของ @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();
    }
}

คุณแน่ใจเกี่ยวกับสิ่งนั้น ตามลิงค์นี้ดูเหมือนว่าฉัน .... stackoverflow.com/questions/1065168/
Timmerz

8

สิ่งที่ฉันได้เรียนรู้ในตอนนี้คือไฟล์ของคุณไม่ได้รับอนุญาตให้มี "." (จุด) ในชื่อไฟล์

A "."  ในชื่อไฟล์ไม่ดี

Templates.plainEmailBodyTemplate-en.txt -> ใช้งานได้ !!!
Templates.plainEmailBodyTemplate.en.txt -> ไม่ทำงานผ่าน GetManifestResourceStream ()

อาจเป็นเพราะเฟรมเวิร์กสับสนกับเนมสเปซและชื่อไฟล์ ...


3
ขอโทษ นี่เป็นสิ่งที่ผิด จุดทำงาน (อย่างน้อยมันก็ใช้งานได้สำหรับฉัน NET4.5) ฉันไม่รู้ว่าทำไมคุณมีข้อบกพร่องนี้
เฟลิกซ์ Keil

ใช่พวกเขาทำงาน แต่พวกเขาทำหน้าที่เป็นตัวแยกไดเรกทอรี Templates.plainEmailBodyTemplate.en.txt จะมองหาทรัพยากร "\ Templates \ plainEmailBodyTemplate \ en.txt"
Peter Gfader

ไม่ฉันลองแล้ว GetManifestResourceStream สามารถเข้าถึงทรัพยากรที่ฝังตัวได้มากกว่าหนึ่งจุดในชื่อไฟล์ (NET4.5)
Felix Keil

1
ฉันมีปัญหาเดียวกันใน. NET 4.5 ไฟล์ที่มีจุดในชื่อไม่ได้ถูกเพิ่มเข้าไปในการรวบรวมทรัพยากร เมธอด assembly.GetManifestResourceNames () ส่งคืนรายการว่างให้ฉันล่าสุดฉันพบว่าปัญหานั้นเกิดจากรหัสภาษาเท่านั้น ca.abcd.sk.crt ไม่ได้ถูกเพิ่มไปยังทรัพยากรในขณะที่ ca.abcd.crt ถูกเพิ่มโดยไม่มีปัญหา
a.farkas2508

1
ยังคงถูกต้องในปี 2020 ขอบคุณมากสำหรับสิ่งนี้ฉันบ้าไปแล้ว
ZeRemz

8

โดยรวมพลังของคุณทั้งหมดฉันใช้คลาสผู้ช่วยนี้สำหรับการอ่านทรัพยากรจากชุดประกอบใด ๆ และ namespace ใด ๆ ในลักษณะทั่วไป

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

3
บวกหนึ่งสำหรับกัปตันดาวเคราะห์: P
Alok

4

ฉันอ่านไฟล์ข้อความที่ใช้ในตัวทรัพยากร:

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

3

ฉันรู้ว่านี่เก่า แต่ฉันแค่อยากจะชี้ให้เห็นถึงNETMF (.Net MicroFramework) คุณสามารถทำสิ่งนี้ได้อย่างง่ายดาย:

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

เนื่องจากNETMFไม่มีGetManifestResourceStream


3

หลังจากอ่านวิธีแก้ปัญหาทั้งหมดที่โพสต์ที่นี่ นี่คือวิธีที่ฉันแก้ไขมัน:

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

3

คำตอบนั้นง่ายมากถ้าคุณเพิ่มไฟล์โดยตรงจาก resources.resx

string textInResourceFile = fileNameSpace.Properties.Resources.fileName;

ด้วยโค้ดบรรทัดนั้นข้อความจากไฟล์จะถูกอ่านโดยตรงจากไฟล์และใส่ลงในตัวแปรสตริง


2

ฉันรำคาญที่คุณต้องรวม namespace และโฟลเดอร์ในสตริงเสมอ ฉันต้องการลดความซับซ้อนของการเข้าถึงทรัพยากรที่ฝังตัว นี่คือเหตุผลที่ฉันเขียนชั้นน้อยนี้ รู้สึกอิสระที่จะใช้และปรับปรุง!

การใช้งาน:

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

}

1
และสิ่งที่เกี่ยวกับการแก้ปัญหาง่ายสุด: var resName = assembly.GetManifestResourceNames () โดยที่ (i => i.EndsWith (fileName)) FirstOrDefault (); มันจะไม่ทำงานถ้าคุณใส่ไดเร็กตอรี่ทั้งชุดเข้าไปด้วย แต่ถ้าอย่างนั้นมันจะเป็นแค่บรรทัดเดียว)
Harry

@Harry แน่ใจว่าคุณสามารถทำได้ สิ่งนี้สัมพันธ์กับคำตอบของฉันอย่างไร คุณต้องการปรับปรุงวิธี GetStream หรือไม่ แล้วคุณจะจัดการกับความคลุมเครือได้อย่างไร?
เฟลิกซ์ Keil

1
@Estevez ใช้ระบบ; ใช้ System.IO; ใช้ System.Linq; ใช้ System.Reflection
Felix Keil

2
ด้วยเหตุผลบางอย่างชั้นเรียนไม่ทำงานเมื่ออยู่ในโครงการอื่น แอสเซมบลีการเรียกและดำเนินการทั้งสองอ้างถึงแอสเซมบลีกับคลาสนี้ไม่ใช่อันที่ดำเนินการทดสอบจริง โดยไม่ต้องเริ่มต้นคงที่และขี้เกียจดีทั้งหมดสรรพสินค้าใหญ่
Curly Brace

1
@CurlyBrace ขอบคุณ การประเมินสันหลังยาวเป็นข้อบกพร่องที่แท้จริงในคำตอบนี้เนื่องจากชุดประกอบการโทรและการดำเนินการเปลี่ยนแปลงขึ้นอยู่กับบริบท พวกเขาจะต้องได้รับการแก้ไขในทุกการเข้าถึง
เฟลิกซ์ Keil

2

บางประเภทโครงการ VS. NET ไม่ได้สร้างไฟล์. NET (.resx) อัตโนมัติ ขั้นตอนต่อไปนี้เพิ่มไฟล์ Resource ให้กับโครงการของคุณ:

  1. คลิกขวาที่โหนดโครงการและเลือกเพิ่ม / รายการใหม่เลื่อนไปที่ไฟล์ทรัพยากร ในกล่องชื่อให้เลือกชื่อที่เหมาะสมตัวอย่างเช่นทรัพยากรแล้วคลิกปุ่มเพิ่ม
  2. ไฟล์รีซอร์ส Resources.resx ถูกเพิ่มเข้ากับโปรเจ็กต์และสามารถมองเห็นเป็นโหนดในโซลูชัน explorer
  3. ที่จริงแล้วมีการสร้างไฟล์สองไฟล์และยังมี C # คลาสที่สร้างขึ้นโดยอัตโนมัติ Resources.Designer.cs อย่าแก้ไขมันถูกปรับปรุงโดย VS Resourcesแฟ้มประกอบด้วยชั้นที่มีชื่อว่า

ตอนนี้คุณสามารถเพิ่มไฟล์ข้อความเป็นทรัพยากรตัวอย่างเช่นไฟล์ xml:

  1. คลิกสองครั้งที่ Resources.resx เลือกเพิ่มทรัพยากร> เพิ่มไฟล์ที่มีอยู่แล้วเลื่อนไปยังไฟล์ที่คุณต้องการรวม ปล่อยให้ค่าเริ่มต้นเป็น Internal for Access Modify
  2. ไอคอนแสดงรายการทรัพยากรใหม่ หากเลือกบานหน้าต่างคุณสมบัติจะแสดงคุณสมบัติ สำหรับไฟล์ xml ภายใต้คุณสมบัติการเข้ารหัสเลือก Unicode (UTF-8) - Codepage 65001 แทนที่จะเป็นเพจรหัสท้องถิ่นเริ่มต้น สำหรับไฟล์ข้อความอื่นเลือกการเข้ารหัสที่ถูกต้องของไฟล์นี้เช่น codepage 1252
  3. สำหรับไฟล์ข้อความเช่นไฟล์ xml คลาสResourcesมีคุณสมบัติประเภทstringที่ตั้งชื่อตามไฟล์ที่รวม ถ้าชื่อไฟล์เป็นเช่น RibbonManifest.xml RibbonManifestแล้วทรัพย์สินที่ควรจะมีชื่อ คุณพบชื่อที่แน่นอนในไฟล์รหัส Resources.Designer.cs
  4. ใช้คุณสมบัติสตริงเช่นคุณสมบัติสตริงอื่น ๆ string xml = Resources.RibbonManifestตัวอย่างเช่น: ResourceFileName.IncludedTextFileNameรูปแบบทั่วไปคือ อย่าใช้ResourceManager.GetStringเนื่องจากฟังก์ชั่น get ของคุณสมบัติสตริงได้ทำมาแล้ว

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

0

นี่เป็นคลาสที่คุณอาจพบว่าสะดวกในการอ่านไฟล์รีซอร์สแบบฝังจากปัจจุบันAssembly:

using System.IO;
using System.Linq;
using System.Text;
using static System.IO.Path;
using static System.Reflection.Assembly;

public static class EmbeddedResourceUtils
{
    public static string ReadFromResourceFile(string endingFileName)
    {
        var 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/3764804
    private 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 = GetDirectoryName(stringBuilder.ToString());
        return fileName == null ? null : new string(fileName.Reverse().ToArray());
    }
}

0

สำหรับทุกคนที่ต้องการข้อความของไฟล์ hardcoded ใน winforms อย่างรวดเร็ว

  1. คลิกขวาที่แอปพลิเคชันของคุณในตัวสำรวจโซลูชัน> ทรัพยากร> เพิ่มไฟล์ของคุณ
  2. คลิกที่มันและในแท็บคุณสมบัติตั้ง "FileType" เป็น "ข้อความ"
  3. ในโปรแกรมของคุณเพียงแค่Resources.<name of resource>.toString();อ่านไฟล์

ฉันจะไม่แนะนำสิ่งนี้ว่าเป็นการปฏิบัติที่ดีที่สุดหรืออะไร แต่มันทำงานได้อย่างรวดเร็วและทำในสิ่งที่จำเป็น


0

สำหรับผู้ใช้ที่ใช้ 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()

หรือ

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

-1

อ่านไฟล์ 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.
}

สร้าง Void สำหรับ IncludeText (), Visual Studio ทำสิ่งนี้ให้คุณ คลิก Lightbulb เพื่อสร้าง CodeBlock อัตโนมัติ

ใส่สิ่งต่อไปนี้ลงใน Generated Code Block

ทรัพยากร 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 และอ่านข้อมูลที่ฝังอยู่ภายในกล่องข้อความเดียว ซึ่งเป็นผลที่ฉันต้องการด้วยตัวอย่างของรหัสนี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.