首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 資源檔案完整指南:.resx、.resources 嵌入與讀取檔案資源

     編輯:關於C語言

前言

.NET 提供兩種資源檔案格式:.resx(XML 格式,設計階段編輯)與 .resources(二進制格式,執行階段載入)。本文詳細說明如何嵌入二進制檔案(圖片、文檔、DLL 等)並透過 ResourceManager 讀取。

兩種資源格式對比

特性.resx.resources
格式XML 文字二進制
設計工具支援Visual Studio 內建編輯器需用工具生成
支援資料型別字串、影像、圖示、檔案參考字串、位元組陣列、序列化物件
編譯輸出編譯為 .resources 嵌入組件直接嵌入組件
適用場景本地化字串、UI 資源大型二進制檔案、外掛載入

方法一:使用 .resx 嵌入檔案(推薦現代專案)

步驟 1:在專案加入資源檔

專案右鍵 → Add → New Item → Resources File → 命名為 Resources.resx

步驟 2:透過設計工具加入檔案

  1. 開啟 Resources.resx 設計工具
  2. 下拉選單選擇 "Files" 或 "Add Existing File"
  3. 選擇要嵌入的檔案(如 template.pdf、logo.png)
  4. 資源名稱自動為檔名(可修改)

步驟 3:程式碼讀取


using System.Resources;
using System.Reflection;

public class ResourceService
{
    private static readonly ResourceManager _rm = new ResourceManager(
        "MyProject.Resources", 
        Assembly.GetExecutingAssembly());

    // 讀取位元組陣列(檔案內容)
    public static byte[] GetFileBytes(string resourceName)
    {
        return _rm.GetObject(resourceName) as byte[];
    }

    // 讀取字串(文字檔)
    public static string GetTextFile(string resourceName)
    {
        byte[] bytes = GetFileBytes(resourceName);
        return bytes != null ? Encoding.UTF8.GetString(bytes) : null;
    }

    // 另存為檔案
    public static void ExtractToFile(string resourceName, string outputPath)
    {
        byte[] data = GetFileBytes(resourceName);
        if (data != null)
            File.WriteAllBytes(outputPath, data);
    }
}

// 使用範例
byte[] pdfBytes = ResourceService.GetFileBytes("template");
ResourceService.ExtractToFile("logo", @"C:\Temp\logo.png");

方法二:手動建立 .resources 檔案(舊版/動態生成)

建立 .resources 檔案


using System.Resources;

public static void CreateResourcesFile()
{
    string outputPath = @"..\..\MyResources.resources";
    
    using (ResourceWriter writer = new ResourceWriter(outputPath))
    {
        // 加入字串
        writer.AddResource("AppTitle", "我的應用程式");
        
        // 加入位元組陣列(檔案內容)
        byte[] pdfData = File.ReadAllBytes(@"C:\Templates\contract.pdf");
        writer.AddResource("ContractTemplate", pdfData);
        
        // 加入影像
        using (var img = Image.FromFile(@"C:\Images\logo.png"))
        using (var ms = new MemoryStream())
        {
            img.Save(ms, ImageFormat.Png);
            writer.AddResource("LogoImage", ms.ToArray());
        }
        
        writer.Generate();
    }
}

編譯時嵌入 .resources 到組件

在專案檔中設定:


<ItemGroup>
  <EmbeddedResource Include="MyResources.resources" />
</ItemGroup>

或在 Visual Studio:檔案屬性 → Build Action = Embedded Resource

讀取嵌入的 .resources


public static class EmbeddedResourceReader
{
    // 命名空間.檔案名(不含副檔名)
    private const string ResourceName = "MyProject.MyResources";

    public static byte[] GetResource(string name)
    {
        using (Stream stream = Assembly.GetExecutingAssembly()
            .GetManifestResourceStream(ResourceName))
        {
            if (stream == null) return null;
            
            using (ResourceReader reader = new ResourceReader(stream))
            {
                foreach (DictionaryEntry entry in reader)
                {
                    if (entry.Key.ToString() == name)
                        return entry.Value as byte[];
                }
            }
            return null;
        }
    }
}

進階主題

多語言本地化(.resx)


// 建立語系專用資源檔
// Resources.zh-TW.resx, Resources.en-US.resx, Resources.ja-JP.resx

// 程式碼自動根據 CurrentUICulture 選擇
Thread.CurrentThread.CurrentUICulture = new CultureInfo("zh-TW");
string title = Resources.AppTitle; // 強型別存取(需啟用自訂工具)

大型檔案處理:串流讀取避免記憶體壓力


public static void ExtractLargeResource(string resourceName, string outputPath)
{
    using (Stream resourceStream = Assembly.GetExecutingAssembly()
        .GetManifestResourceStream($"MyProject.Resources.{resourceName}"))
    using (FileStream fileStream = new FileStream(outputPath, FileMode.Create))
    {
        resourceStream?.CopyTo(fileStream); // 串流複製,不載入完整記憶體
    }
}

動態載入外部 .resources 檔案(外掛架構)


public static ResourceManager LoadExternalResources(string dllPath)
{
    Assembly assembly = Assembly.LoadFrom(dllPath);
    // 假設資源命名為 PluginName.Resources
    string resourceName = assembly.GetName().Name + ".Resources";
    return new ResourceManager(resourceName, assembly);
}

常見問題與解決

問題原因解決
GetObject 回傳 null資源名稱不符(區分大小寫、命名空間前綴)用 GetManifestResourceNames() 列出所有資源名稱確認
編譯後找不到資源Build Action 非 Embedded Resource檔案屬性設為 Embedded Resource
中文檔名亂碼資源名稱編碼問題資源名稱僅用 ASCII,實際檔名存放在資源內容中
記憶體不足大檔案一次性載入 byte[]使用 GetManifestResourceStream 串流處理

現代替代方案

  • Embedded File Provider (ASP.NET Core):IFileProvider 統一存取嵌入檔案與實體檔案
  • Source Generators:編譯期生成強型別資源存取類別
  • NuGet 套件資源:透過 Microsoft.Extensions.FileProviders.Embedded 管理

總結

掌握 .resx/.resources 嵌入與讀取技巧,可將設定檔、範本、靜態資產封裝在組件內,簡化部署。現代專案優先使用強型別 .resx 配合 Source Generator,大型二進制檔案採串流讀取,外掛架構則動態載入獨立 .resources 組件。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved