使用ResourceReader和ResourceSet解析二进制资源文件
建议先读这篇文章来先了解IResourceReader,IResourceWriter和ResourceSet类型:..NET(C#):使用IResourceReader,IResourceWriter和ResourceSet。这里就不在讲这三个类型的使用。
上面讲过,RESX资源文件最终会被编译成.resources扩展名的资源文件(二进制)并保存在程序集清单资源(assembly manifest resource)。
下面我们用.NET中的.resources二进制资源文件的解析类ResourceReader和ResourceSet来手动解析这个.resources文件。
代码:
static void Main()
{
using (Stream resources = Assembly.GetExecutingAssembly().GetManifestResourceStream("Mgen.Resource1.resources"))
{
//使用IResourceReader
ReadUsingResourceReader(resources);
//重新定位Stream
resources.Seek(0, SeekOrigin.Begin);
//使用ResourceSet
ReadUsingResourceSet(resources);
}
}
//使用IResourceReader
static void ReadUsingResourceReader(Stream st)
{
Console.WriteLine("== 使用IResourceReader");
IResourceReader rr = new ResourceReader(st);
var iter = rr.GetEnumerator();
while (iter.MoveNext())
Console.WriteLine("键: {0} 值: {1}", iter.Key, iter.Value);
//不需要调用IResourceReader.Dispose,Stream会在Main方法中被Dipose
}
//使用ResourceSet
static void ReadUsingResourceSet(Stream st)
{
Console.WriteLine("== 使用ResourceSet");
ResourceSet rs = new ResourceSet(new ResourceReader(st));
Console.WriteLine(BitConverter.ToString((byte[])rs.GetObject("b")));
Console.WriteLine(rs.GetString("String1"));
//不需要调用ResourceSet.Dispose,Stream会在Main方法中被Dipose
}
这将会以ResourceReader和ResourceSet两种方式输出b.file的字节内容和String1字符串。
使用ResourceManager解析二进制资源文件
关于ResourceManager类型的使用,可以参考.NET(C#):使用ResourceManager类型。这里就不再多讲了。
我们就直接使用ResourceManager,还是上面的工程,用ResourceManager来解析这个.resources二进制的资源文件。
代码:
ResourceManager resManager = new ResourceManager(typeof(Resource1));
//等效于:new ResourceManager("Mgen.Resource1", Assembly.GetExecutingAssembly());
//此时ResourceManager.BaseName是Type.FullName正好是Mgen.Resource1
//获取file.b的内容
Console.WriteLine(BitConverter.ToString((byte[])resManager.GetObject("b")));
//获取资源中的字符串
Console.WriteLine(resManager.GetString("String1"));
这将会输出b.file的字节内容和String1字符串。
小看RESX资源文件的Designer.cs文件
最后再让我们看看RESX资源文件后面的那个xxx.Designer.cs文件。
它定义了资源读取的一个类,比如资源文件名称是Resource1,这个类的名称就是Resource1。这个类其实就是内部包装了一个上面讲的ResourceManager,并且根据用户RESX定义的资源数据显示的定义具有强类型的属性值用来读取文件。
其内部ResourceManager是这样被初始化的,可以看到,ResourceManager.BaseName就是程序集清单资源的名称(注意ResourceManager.BaseName属性没有CultureInfo名称和.resources扩展名,但是有命名空间(其实完全就是文件名),所以本例中的Mgen.Resource1.resources程序集清单资源文件的ResourceManager初始化BaseName就是:Mgen.Resource1。)
static void Main()
{
using (Stream resources = Assembly.GetExecutingAssembly().GetManifestResourceStream("Mgen.Resource1.resources"))
{
//使用IResourceReader
ReadUsingResourceReader(resources);
//重新定位Stream
resources.Seek(0, SeekOrigin.Begin);
//使用ResourceSet
ReadUsingResourceSet(resources);
}
}
//使用IResourceReader
static void ReadUsingResourceReader(Stream st)
{
Console.WriteLine("== 使用IResourceReader");
IResourceReader rr = new ResourceReader(st);
var iter = rr.GetEnumerator();
while (iter.MoveNext())
Console.WriteLine("键: {0} 值: {1}", iter.Key, iter.Value);
//不需要调用IResourceReader.Dispose,Stream会在Main方法中被Dipose
}
//使用ResourceSet
static void ReadUsingResourceSet(Stream st)
{
Console.WriteLine("== 使用ResourceSet");
ResourceSet rs = new ResourceSet(new ResourceReader(st));
Console.WriteLine(BitConverter.ToString((byte[])rs.GetObject("b")));
Console.WriteLine(rs.GetString("String1"));
//不需要调用ResourceSet.Dispose,Stream会在Main方法中被Dipose
}
接着RESX中定义的文件b和字符串String1资源完全就是ResourceManager的方法的包装,比如b文件读取返回字节数组,就是调用ResourceManager.GetObject,然后转换成byte[]:
get {
object obj = ResourceManager.GetObject("b", resourceCulture);
return ((byte[])(obj));
}
}
好了,就到这里吧,希望读者读完文章后对RESX文件和程序集清单资源有更好的理解!
原文链接:http://www.cnblogs.com/mgen/archive/2011/12/11/2283917.html