创建资源文件

更新:2010 年 12 月

可以将资源(例如,字符串、图像或对象数据)包含在资源文件中,以供应用程序轻松使用。 .NET Framework 提供了创建资源文件的五种方法:

  • 创建一个包含字符串资源的文本文件。 可以使用资源文件生成器 (Resgen.exe) 将该文本文件转换为二进制资源 (.resources) 文件。 然后,可以使用语言编译器将该二进制资源文件嵌入应用程序可执行文件或应用程序库中,或者可以使用程序集链接器 (Al.exe) 将该二进制资源文件嵌入附属程序集中。 有关更多信息,请参见文本文件中的资源一节。

  • 创建一个包含字符串、图像或对象数据的 XML 资源 (.resx) 文件。 可以使用资源文件生成器 (Resgen.exe) 将 .resx 文件转换为二进制资源 (.resources) 文件。 然后,可以使用语言编译器将该二进制资源文件嵌入应用程序可执行文件或应用程序库中,或者可以使用程序集链接器 (Al.exe) 将该二进制资源文件嵌入附属程序集中。 有关更多信息,请参见 .resx 文件中的资源一节。

  • 使用 System.Resources 命名空间中的类型以编程方式创建一个 XML 资源 (.resx) 文件。 可以创建一个 .resx 文件,枚举其资源并按名称检索特定资源。 有关更多信息,请参见主题以编程方式使用 .resx 文件

  • 以编程方式创建一个二进制资源 (.resources) 文件。 然后,可以使用语言编译器将该文件嵌入应用程序可执行文件或应用程序库中,或者可以使用程序集链接器 (Al.exe) 将该文件嵌入附属程序集中。 有关更多信息,请参见 .resources 文件中的资源一节。

  • 使用 Visual Studio 创建一个资源文件,并将该文件包含在您的项目中。 Visual Studio 提供了一个资源编辑器,可用于添加、删除和修改资源。 编译时,该资源文件会自动转换为一个二进制 .resources 文件,并会嵌入应用程序程序集或附属程序集中。 有关更多信息,请参见 Visual Studio 中的资源文件一节。

文本文件中的资源

文本 (.txt) 文件只能用来存储字符串资源;对于非字符串资源,请使用 .resx 文件或以编程方式创建它们。 包含字符串资源的文本文件具有以下格式:

# This is an optional comment.
name = value

; This is another optional comment.
name = value

字符串资源显示为 name/value 对,其中 name 是标识资源的字符串,而 value 是在将 name 传递到资源检索方法(例如 ResourceManager.GetString)时返回的资源字符串。 name 和 value 用等号 (=) 分隔开。

警告说明警告

不要使用资源文件来存储密码、安全敏感信息或保密数据。

注释在文本文件中是可选的,并且注释行均以分号 (;) 或井号 (#) 开头。 可将包含注释的行放置在文件中的任意位置。 使用资源文件生成器 (Resgen.exe) 创建的已编译 .resources 文件中不包含注释。

文本文件中的任意空行将视为空白,并将被忽略。

下面的示例定义了分别名为 OKButton 和 CancelButton 的两个字符串资源。

#Define resources for buttons in the user interface.
OKButton=OK
CancelButton=Cancel

如果 .txt 文件包含 name 的重复匹配项,则资源文件生成器 (Resgen.exe) 将显示一条警告并忽略第二个名称。

value 不能包含换行符,但您可以使用 C 语言样式的转义符(如使用 \n 表示新行,使用 \t 表示制表符)。 此外,允许使用空字符串。

可以使用 little-endian 或 big-endian 字节顺序的 UTF-8 编码或 UTF-16 编码以文本文件格式保存资源。 但是,资源文件生成器 (Resgen.exe)(它可将 .txt 文件转换为 .resources 文件)默认情况下会将文件视为 UTF-8。 若要让 Resgen.exe 识别使用 UTF-16 编码的文件,必须在该文件的开头包含 Unicode 字节顺序标记 (U+FEFF)。

若要将一个文本格式的资源文件嵌入 .NET Framework 程序集中,则必须使用资源文件生成器 (Resgen.exe) 将该文件转换为二进制资源 (.resources) 文件。 然后,可以使用语言编译器将 .resources 文件嵌入 .NET Framework 程序集中,或者可以使用程序集链接器 (Al.exe) 将该文件嵌入附属程序集中。

下面的示例对一个简单的“Hello World”控制台应用程序使用一个名为 GreetingResources.txt 的文本格式的资源文件。 该文本文件定义了 prompt 字符串和 greeting 字符串,二者提示用户输入其姓名并显示一句问候语。

# GreetingResources.txt 
# A resource file in text format for a "Hello World" application.
#
# Initial prompt to the user.
prompt=Enter your name: 
# Format string to display the result.
greeting=Hello, {0}!

使用以下命令将文本文件转换为 .resources 文件:

resgen GreetingResources.txt

下面的示例显示了控制台应用程序的源代码,该应用程序使用 .resources 文件向用户显示消息。

Imports System.Reflection
Imports System.Resources

Module Example
   Public Sub Main()
      Dim rm As New ResourceManager("GreetingResources", 
                                    Assembly.GetExecutingAssembly())
      Console.Write(rm.GetString("prompt"))
      Dim name As String = Console.ReadLine()
      Console.WriteLine(rm.GetString("greeting"), name)                                                                          
   End Sub
End Module
' The example displays output like the following:
'       Enter your name: Wilberforce
'       Hello, Wilberforce!
using System;
using System.Reflection;
using System.Resources;

public class Example
{
   public static void Main()
   {
      ResourceManager rm = new ResourceManager("GreetingResources", 
                               Assembly.GetExecutingAssembly());
      Console.Write(rm.GetString("prompt"));
      string name = Console.ReadLine();
      Console.WriteLine(rm.GetString("greeting"), name);                                                                          
   }
}
// The example displays output like the following:
//       Enter your name: Wilberforce
//       Hello, Wilberforce!

如果您使用的是 Visual Basic 且源代码文件名为 Greeting.vb,则以下命令将创建一个包含嵌入的 .resources 文件的可执行文件:

vbc greeting.vb /resource:GreetingResources.resources

如果您使用的是 C# 且源代码文件名为 Greeting.cs,则以下命令将创建一个包含嵌入的 .resources 文件的可执行文件:

csc greeting.cs /resource:GreetingResources.resources

.resx 文件中的资源

与只能存储字符串资源的文本文件不同,XML 资源 (.resx) 文件可存储字符串、二进制数据(例如,图像、图标和音频剪辑)以及编程对象。 .resx 文件包含一个标准标头,该标头描述资源项的格式并指定用来分析数据的 XML 版本控制信息。 资源文件数据位于 XML 标头后。 每个数据项均由包含在 data 标记中的名称/值对组成。 其 name 特性定义了资源名称,并且嵌套的 value 标记包含资源值。 对于字符串数据,value 标记包含字符串。

例如,下面的 data 标记定义了一个名为 prompt 的字符串资源,其值为“Enter your name:”。

  <data name="prompt" xml:space="preserve">
    <value>Enter your name:</value>
  </data>
警告说明警告

不要使用资源文件来存储密码、安全敏感信息或保密数据。

对于资源对象,data 标记包含一个 type 特性,该特性指示资源的数据类型。 对于包含二进制数据的对象,data 标记还包含一个 mimetype 特性,该特性指示二进制数据的 base64 类型。

注意注意

所有 .resx 文件都使用二进制序列化格式化程序来生成和分析特定类型的二进制数据。因此,如果对象的二进制序列化格式出现了不可兼容的变化,.resx 文件可能会变为无效。

下面的示例演示了 .resx 文件的一部分,该文件包含一个 Int32 资源和一个位图图像。

<data name="i1" type="System.Int32, mscorlib">
  <value>20</value>
</data>

<data name="flag" type="System.Drawing.Bitmap, System.Drawing,   
    Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" 
    mimetype="application/x-microsoft.net.object.bytearray.base64">
  <value>
    AAEAAAD/////AQAAAAAAAAAMAgAAADtTeX…
  </value>
</data>
重要说明重要事项

由于 .resx 文件必须由预定义格式的格式良好的 XML 组成,因此,我们建议不要手动处理 .resx 文件,特别是在 .resx 文件包含字符串以外的资源时。相反,Visual Studio 提供了一个透明接口,用于创建和操作 .resx 文件;有关更多信息,请参见 Visual Studio 中的资源文件一节。还可以通过编程方式创建和操作 .resx 文件。有关更多信息,请参见以编程方式使用 .resx 文件

.resources 文件中的资源

可以使用 System.Resources.ResourceWriter 类直接从代码中以编程方式创建二进制资源 (.resources) 文件。 还可以使用资源文件生成器 (Resgen.exe) 从文本文件或 .resx 文件创建 .resources 文件。 除字符串数据外,.resources 文件还可包含二进制数据(字节数组)和对象数据。 以编程方式创建 .resources 文件需要执行以下步骤:

  1. 创建一个具有唯一文件名的 ResourceWriter 对象。 可以通过为 ResourceWriter 类构造函数指定文件名或文件流来做到这一点。

  2. 对于要添加到该文件的每个命名资源,调用 ResourceWriter.AddResource 方法的重载之一。 资源可以是字符串、对象或二进制数据(字节数组)集合。

  3. 调用 ResourceWriter.Close 方法以将资源写入该文件并关闭 ResourceWriter 对象。

注意注意

不要使用资源文件来存储密码、安全敏感信息或保密数据。

下面的示例以编程方式创建了一个名为 CarResources.resources 的 .resources 文件,该文件存储了六个字符串、一个图标和两个应用程序定义的对象(两个 Automobile 对象)。 请注意,该示例中定义和实例化的 Automobile 类标记了 SerializableAttribute 特性,这使它将为二进制序列化格式化程序所保存。

Imports System.Drawing
Imports System.Resources

<Serializable()> Public Class Automobile
   Private carMake As String
   Private carModel As String
   Private carYear As Integer
   Private carDoors AS Integer
   Private carCylinders As Integer

   Public Sub New(make As String, model As String, year As Integer) 
      Me.New(make, model, year, 0, 0)   
   End Sub

   Public Sub New(make As String, model As String, year As Integer, 
                  doors As Integer, cylinders As Integer)
      Me.carMake = make
      Me.carModel = model
      Me.carYear = year
      Me.carDoors = doors
      Me.carCylinders = cylinders
   End Sub

   Public ReadOnly Property Make As String
      Get
         Return Me.carMake
      End Get   
   End Property       

   Public ReadOnly Property Model As String
      Get
         Return Me.carModel
      End Get   
   End Property       

   Public ReadOnly Property Year As Integer
      Get
         Return Me.carYear
      End Get   
   End Property       

   Public ReadOnly Property Doors As Integer
      Get
         Return Me.carDoors
      End Get   
   End Property       

   Public ReadOnly Property Cylinders As Integer
      Get
         Return Me.carCylinders
      End Get   
   End Property       
End Class

Module Example
   Public Sub Main()
      ' Instantiate an Automobile object.
      Dim car1 As New Automobile("Ford", "Model N", 1906, 0, 4)
      Dim car2 As New Automobile("Ford", "Model T", 1909, 2, 4)
      ' Define a resource file named CarResources.resx.
      Using rw As New ResourceWriter(".\CarResources.resources")
         rw.AddResource("Title", "Classic American Cars")
         rw.AddResource("HeaderString1", "Make")
         rw.AddResource("HeaderString2", "Model")
         rw.AddResource("HeaderString3", "Year")
         rw.AddResource("HeaderString4", "Doors")
         rw.AddResource("HeaderString5", "Cylinders")
         rw.AddResource("Information", SystemIcons.Information) 
         rw.AddResource("EarlyAuto1", car1)
         rw.AddResource("EarlyAuto2", car2)  
      End Using
   End Sub
End Module
using System;
using System.Drawing;
using System.Resources;

[Serializable()] public class Automobile
{
   private string carMake;
   private string carModel;
   private int carYear;
   private int carDoors;
   private int carCylinders;

   public Automobile(string make, string model, int year) :
                     this(make, model, year, 0, 0)
   { }

   public Automobile(string make, string model, int year, 
                     int doors, int cylinders)
   {                     
      this.carMake = make;
      this.carModel = model;
      this.carYear = year;
      this.carDoors = doors;
      this.carCylinders = cylinders;
   }

   public string Make {
      get { return this.carMake; }
   }       

   public string Model {
      get { return this.carModel; } 
   }       

   public int Year {
      get { return this.carYear; }
   }       

   public int Doors {
      get { 
         return this.carDoors; }
   }       

   public int Cylinders {
      get { 
         return this.carCylinders; }
   }        
}

public class Example
{
   public static void Main()
   {
      // Instantiate an Automobile object.
      Automobile car1 = new Automobile("Ford", "Model N", 1906, 0, 4);
      Automobile car2 = new Automobile("Ford", "Model T", 1909, 2, 4);
      // Define a resource file named CarResources.resx.
      using (ResourceWriter rw = new ResourceWriter(@".\CarResources.resources"))
      {
         rw.AddResource("Title", "Classic American Cars");
         rw.AddResource("HeaderString1", "Make");
         rw.AddResource("HeaderString2", "Model");
         rw.AddResource("HeaderString3", "Year");
         rw.AddResource("HeaderString4", "Doors");
         rw.AddResource("HeaderString5", "Cylinders");
         rw.AddResource("Information", SystemIcons.Information); 
         rw.AddResource("EarlyAuto1", car1);
         rw.AddResource("EarlyAuto2", car2);  
      }
   }
}

在创建 .resources 文件后,可以通过包含语言编译器的 /resource 开关将该文件嵌入运行时可执行文件或库中,或者可以通过使用程序集链接器 (Al.exe) 将该文件嵌入附属程序集中。

Visual Studio 中的资源文件

在向 Visual Studio 项目中添加资源文件时,Visual Studio 会在项目目录中创建一个 .resx 文件。 Visual Studio 提供了一个资源编辑器,可用于添加字符串、图像和二进制对象。 由于编辑器设计为仅处理静态数据,因此无法使用编辑器存储编程对象;您必须以编程方式将对象数据写入 .resx 文件或 .resources 文件。 有关更多信息,请参见以编程方式使用 .resx 文件主题和 .resources 文件中的资源一节。

如果您添加的是本地化资源,则应为这些资源提供与主资源文件相同的根文件名,并且还应在文件名中指定其区域性。 例如,如果您添加一个名为 Resources.resx 的资源文件,则还可以创建名为 Resources.en-US.resx 和 Resources.fr-FR.resx 的资源文件以分别保留英语(美国)和法语(法国)区域性的本地化资源。 还应指定您的应用程序的默认区域性。 这是在找不到特定区域性的任何本地化资源时将使用其资源的区域性。 若要指定默认区域性,请在 Visual Studio 的解决方案资源管理器中,右击项目名称,指向“应用程序”,再单击**“程序集信息”,然后在“非特定语言”**列表中选择相应的语言/区域性。

编译时,Visual Studio 首先会将项目中的 .resx 文件转换为二进制资源 (.resources) 文件,然后在项目的 obj 目录的子目录中存储这些文件。 Visual Studio 会将不包含本地化资源的任何资源文件嵌入项目所生成的主程序集中。 如果任何资源文件包含本地化资源,则 Visual Studio 会将它们嵌入每个本地化区域性的单独附属程序集中。 然后,它会将各个附属程序集存储在其名称与本地化区域性对应的目录中。 例如,本地化的英语(美国)资源将存储在 en-US 子目录中的附属程序集中。

请参见

参考

System.Resources

概念

应用程序中的资源

打包和部署资源

修订记录

日期

修订记录

原因

2010 年 12 月

做了大范围修订。

信息补充。