關於資源文件的相關操做。
//1.比較常見的有獲取資源文件對應的文件流,而後轉換到相對應的文件
//比較典型的作法是經過代碼程序集加載指定資源
//以下經過Assembly的靜態方法GetExecutingAssembly()獲得程序集
//還有不少方式能夠獲得代碼程序集
System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
Stream manifestResourceStream = null;
manifestResourceStream = asm.GetManifestResourceStream("MyLibrary." + filename);
return manifestResourceStream;
//獲得該文件流,這裏也能夠是字符流。
//若是咱們資源文件對應的該清單是一個圖片文件
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(manifestResourceStream, true);
//若是咱們的資源文件是光標文件
Cursor cursor = new Cursor(manifestResourceStream);
//圖標
Icon icon = new Icon(manifestResourceStream);
//字符串
System.IO.StreamReader sr = new System.IO.StreamReader(manifestResourceStream);
string str = sr.ReadLine();
//2.另一種寫法,主要是經過ResourceManager類的GetObject()方法
//也能夠經過GetStream()獲得流後執行操做.
System.Resources.ResourceManager manager =
new System.Resources.ResourceManager("資源名稱", Assembly.GetExecutingAssembly());
Object target = manager.GetObject("資源文件名");//獲取到指定的資源的值
//在這裏對應咱們加入到資源文件的清單,
//轉換回我沒的目標值,可能會產生一個拆箱的過程
//若是咱們資源文件對應的該清單是一個圖片文件System.Drawing.Bitmap bitmap = (System.Drawing.Bitmap)target;
//若是咱們的資源文件是光標文件
Cursor cursor = (Cursor)target;
//圖標
Icon icon = (Icon)target;
//字符串
string str = target.ToString();//或者manager
manager.GetString("資源文件名");
//經過以上兩種操做,就能夠從資源文件中進行一個指定資源的加載了。
//前提是你的資源清單理存在該資源哦。
//推薦使用第種方法,這種方法也是MS Resx裏對資源文件的操做方法。
//如今咱們已經能夠讀取資源文件了,如今開始寫資源文件的操做。
//3.固然,你能夠直接經過設計界面來添加一個資源文件,
//切記將生成操做改成「嵌入的資源」,Embed
System.Resources.ResourceWriter writer =
new System.Resources.ResourceWriter("dongpad.com.resources");
writer.AddResource("bitmap", Image.FromFile(@"dongpad.bitmap"));
writer.AddResource("cursor", Image.FromFile(@"dongpad.cursor"));
writer.AddResource("ico", Image.FromFile(@"dongpad.ico"));
writer.AddResource("str", Image.FromFile(@"dongpad.str"));
//在這裏資源的名稱記得要惟一。
writer.Generate();
writer.Close();
//下次給你們總結一下關於C#開發中經常使用的一些重寫。但願你們支持!
--參考文獻--------------------------------------------------------------------------
什麼是資源文件
在 .NET 中準備 World-Ready 程序時須要三步,Globalization,Localizability 和 Localization。在這第三步的 Localization 中就是使用資源文件最多見的地方。(本文不討論 World-Ready 程序,或許之後在另外一篇文章中)由於程序的邏輯界面須要與資源界面隔離,而資源界面就是咱們所說的資源文件。顧名思義,一個資源文件中固然全是資源,不過,什麼是資源?這裏所謂的資源就是程序中可利用的數據,譬如:字符串、圖片和任何二進制數據,包括任何類型的文件。注意一個資源文件能夠有多種語言版本,舉例,一個 Strings.resources 文件能夠有英語版、簡體中文版、繁體中文版等。 ResourceManager 能夠自動根據文件名來確認調用哪一個版本。不一樣的版本只要在文件名中添入區域語言就能夠了。好比,咱們的 Strings.resources 是默認版,英語版的能夠是 Strings.en-US.resources(美國英文),簡體中文的能夠是 Strings.zh-CHS.resources(簡體中文),而繁體中文的就能夠是 Strings.zh-CHT.resources(繁體中文)。所謂的默認版就是當找不到適當的資源版本時用的資源,通常都是英文。默認文件應當被嵌入到主 Assembly 中,這樣就不會發生找不到資源的錯誤。在 VS.NET 中將一個文件的屬性設爲 Embedded Resource 可使資源被嵌入到主 Assembly 中。
資源文件類型
System.Resources 名字空間支持三種資源文件:
.txt 文件,只能有字符串資源。由於不能被嵌入到 Assembly 中,因此很容易暴露,被客戶修改。最大缺點是僅支持字符串資源,因此不推薦使用。
.resx 文件,由 XML 組成,能夠加入任何資源,包括二進制。一樣不能被嵌入到 Assembly 中。在 System.Resources 名字空間中有專用讀寫的類。VS.NET 建立這種文件而後將其轉成 .resources 文件並根據設置將其嵌入到 Assembly 中。
.resources 文件,PE 格式,能夠加入任何資源。惟一能夠被嵌入到 Assembly 的文件,在 System.Resources 名字空間中有專用讀寫的類。
調用資源文件的幾種方法
ResourceManager 能夠根據不一樣的 UICulture 設置返回不一樣的本地資源(這與 World-Ready 程序有關,在此不討論),咱們只需知道調用資源用到它就能夠了。接下來讓咱們看看如何調用每一種:
.txt 文件:
不能夠直接調用,得先將其轉換成 .resources 文件才能使用。(關於如何轉換請看"推薦工具")
.resx 文件:
能夠用 ResXResourceReader 來作讀取,可是這種方法不直觀,不推薦直接調用 .resx 文件。正確的方法是將其轉換成 .resources 文件,而後用 ResourceManager 做讀取工做。注意若是是在 VS.NET 中添加的 .resx 文件,那麼它們自動被設爲 Embedded Resource,轉成 .resources 文件後被嵌入到 Assembly 中。
.resources 文件:
分紅兩種狀況:
被嵌入或編譯成 Satellite Assembly:
用 ResourceManager 的各類 constructor 來得到在 Assembly 中的資源。
單獨文件,沒被編譯或嵌入到 Assembly 中:
能夠用 ResourceManager.CreateFileBasedResourceManager 來得到資源集(ResourceSet),就是全部的資源。
特殊狀況:
還有一種特殊狀況,那就是當你直接嵌入一資源時,也就是說,不經過一個資源文件而直接將一資源嵌入到 Assembly 中。這能夠在 VS.NET 中經過設置一文件的 Build 屬性爲 Embedded Resource 實現。在這種狀況下 ResourceManager 就沒有用了,由於它只能獲取 .resources 資源文件(在或不在 Assembly 中)。那麼如何調用這類的資源呢?不難,咱們須要利用一些 Reflection 中的特徵。別怕,不是讓你再學 Reflection,其實咱們只要瞭解一些 System.Reflection.Assembly 這個類中的一些函數就能夠了。有三個相關函數,不過咱們只須要 Assembly.GetManifestResourceStream 這個函數。這個函數將一嵌入到 Assembly 中的資源以 stream 的方式返回,而咱們能夠將這個 stream 轉成在 .NET 中可用的對象。好比,若是嵌入資源是一圖片,那麼咱們能夠利用 New Bitmap(Stream) 這個 Bitmap 的 constructor 得到這個圖片資源的 Bitmap 對象。
注:在這裏僅介紹怎樣得到不一樣的資源的方法,關於怎樣用各個類與函數請參看有關文檔。
如何準確的定義資源文件的邏輯位置
我想這是許多人最關注的一段了!在這裏做者將解說如何正確的填寫 ResouceManager(String, Assembly) 這個 constructor,還有如何正確的填寫 Assembly.GetManifestResourceStream(String),由於它們兩個的原理是相同的。看過了上面的描述,到了這裏就簡單多了。這裏主要討論的是怎麼填寫那個 String。這個 String 就是資源的完整名,一個完整名由它的名字空間和文件名前部分(BaseName)組成。例如,若是默認名字空間(root namespace)是 DefaultNamespace,資源文件的名字是 Strings.en-US.resources,那麼它的完整名就是 DefaultNamespace.Strings。這個很簡單,不過怎樣肯定名字空間呢?這就有些奇怪了,由於 C# 的編譯器與 VB.NET 的編譯器有些不一樣。做者在這裏分別給出兩個編譯器怎樣給嵌入資源自動添加命名空間:
C#
它自動添加 default namespace(與 root namespace 相同),但也添加子文件夾的名字。例如,在 Subfolder 子文件夾下放的資源文件 Strings.en-US.resources,它的完整名是 default namespace + subfolder + base name = DefaultNamespace.Subfolder.Strings
VB.NET
在 VB.NET 中就很簡單了,它自動給嵌入資源添加 root namespace。無論你在哪一個子文件夾中放置資源文件,資源文件的完整名永遠是 root namespace + base name。
根據上面的描述,若是咱們使用 C#,用 VS.NET 在 NewFolder 這個子文件夾中添加了一個叫 Images.resources 的資源文件,那麼咱們應該用如下代碼獲取這些資源,假設 default namespace 是 MyDefault:
ResourceManager res = new ResourceManager("MyDefault.NewFolder.Images", this.GetTy函數