目錄
一、概念:.net與c#
net/dotnet:一般指.Net Framework框架.一種平臺,一種技術.
C#(sharp):一種編程語言,可以開發基於.net平臺的應用
二、.NET兩種交互模式
•C/S:客戶機(Client)/服務器模式(Server) 如:qq
(C/S是Client/Server的縮寫。客戶端需要安裝專用的客戶端軟件。)
•B/S:瀏覽器(Browser)/服務器模式(Server)
(B/S是Brower/Server的縮寫,客戶機上只要安裝一個瀏覽器)
三、IDE介紹
•IDE(Integrated Development,集成開發環境)
•Visual Studio 2010 簡介:
–一套完整的開發工具集
–用於開發桌面應用程序、ASP.NET Web 應用程序、XML、Web Service、移動應用程序
–爲快速開發提供強大支持(.net的IDE就是vs2010、vs2012、vs2013)
四、vs文件解讀
•.Sln:解決方案文件
•.csproj:項目文件
•.cs:類文件
五、VS中的常用快捷鍵
•Ctrl+K+D:快速對齊代碼
•Ctrl+Z:撤銷
•Ctrl+S:保存(一定要經常保存!)
•Ctrl+J:快速彈出智能提示
•Shift+End 、Shift+Home
•Ctrl+K+C:註釋所選代碼
•Ctrl+K+U:取消對所選代碼的註釋
•F1:轉到幫助文檔
•Alt+F10:快速添加命名空間
•摺疊冗餘代碼:#Region 和#EndRegion
•雙擊tab鍵補全代碼結構
大小寫轉換
轉小寫 組合鍵:Ctrl+ U
轉大寫 組合鍵:CTRL + SHIFT + U
刪除一行
(1) Ctrl +L
(2) Ctrl +shift +L
(3) Shift +上下鍵+Backspace
跳轉到指定的某一行
組合鍵:Ctrl+G
矩形區域選擇
組合鍵:Shift+Alt+鼠標拖動 (很適合區域代碼塊選擇)
VS2017 C#字段自動生成屬性的快捷鍵:
https://jingyan.baidu.com/article/fdffd1f8653885f3e98ca13a.html
vs2017快捷鍵補充:https://www.cnblogs.com/lsgxeva/p/7944986.html
六、變量的命名
•命名規則:
–1 必須以“字母”_或@符號開頭.--不要以數字開頭
–2 後面可以跟任意“字母”、數字、下劃線.
–注意:
•1)你起的變量名不要與c#系統中的關鍵字重複.
•2)在c#中,大小寫是敏感的.
•3)同一個變量名不允許重複定義(先這麼認爲,不嚴謹)
•定義變量時,變量名要有意義
•C# 變量命名編碼規範——Camel 命名法:
–首個單詞的首字母小寫,其餘單詞的首字母大寫。
•Pascal命名命名規範:每一個單詞第一字母都大寫
•如果使用到英文單詞的縮寫,全部用大寫!
七、算術運算符及算術表達式
•算術運算符: + - * / %(取餘數 取模)
•算術表達式:由算術運算符連接起來的式子.如:1+1 a-b(變量ab前面已聲明並賦初值)
•演示:某學生三門課成績爲,語文:90 數學:80 英語:67,編程求總分和平均分.
•優先級:先乘除,後加減,有括號先算括號裏的,相同級別的從左至右運算 int a=((1+5)+3)*2
•小括號可以無限制的套用,但一定要成對出現.
八、部分數據類型
所有的類型都能夠轉換成string類型,調用ToString()。
1、枚舉
語法:
[public] enum 枚舉名
{
值1,
值2,
值3,
........
}
public:訪問修飾符。公開的公共的,哪都可以訪問。
enum:關鍵字,聲明枚舉的關鍵字
枚舉名:要符合Pascal命名規範
我們可以將一個枚舉類型的變量跟int類型和string類型互相轉換。
枚舉類型默認是跟int類型相互兼容的,所以可以通過強制類型轉換的語法互相轉換。
當轉換一個枚舉中沒有的值的時候,不會拋異常,而是直接將數字顯示出來。
枚舉同樣也可以跟string類型互相轉換,如果將枚舉類型轉換成string類型,則直接調用ToString().
如果將字符串轉換成枚舉類型則需要下面這樣一行代碼:
(要轉換的枚舉類型)Enum.Parse(typeof(要轉換的枚舉類型),"要轉換的字符串");
如果轉換的字符串是數字,則就算枚舉中沒有,也會不會拋異常。
如果轉換的字符串是文本,如果枚舉中沒有,則會拋出異常。
2、常量
聲明的常量的語法:
const 變量類型 變量名=值;
3、結構
可以幫助我們一次性聲明多個不同類型的變量。
語法:
[public] struct 結構名
{
成員;//字段
}
變量在程序運行期間只能存儲一個值,而字段可以存儲多個值。
4、數組
一次性存儲多個相同類型的變量。
語法:
數組類型[] 數組名=new 數組類型[數組長度];
5、字符串
1)、字符串的不可變性
當你給一個字符串重新賦值之後,老值並沒有銷燬,而是重新開闢一塊空間存儲新值。
當程序結束後,GC掃描整個內存,如果發現有的空間沒有被指向,則立即把它銷燬。
2)、我們可以講字符串看做是char類型的一個只讀數組。
ToCharArray();將字符串轉換爲char數組
new string(char[] chs):能夠將char數組轉換爲字符串
字符串提供的各種方法
1)、Length:獲得當前字符串中字符的個數
2)、ToUpper():將字符轉換成大寫形式
3)、ToLower():將字符串轉換成小寫形式
4)、Equals(lessonTwo,StringComparison.OrdinalIgnoreCase):比較兩個字符串,可以忽略大小寫
5)、Split():分割字符串,返回字符串類型的數組。
6)、Substring():解決字符串。在截取的時候包含要截取的那個位置。(配合charindex解決複雜字符串)
7)、IndexOf():判斷某個字符串在字符串中第一次出現的位置,如果沒有返回-1、值類型和引用類型在內存上存儲的地方不一樣。
8)、LastIndexOf():判斷某個字符串在字符串中最後一次出現的位置,如果沒有同樣返回-1
9)、StartsWith():判斷以....開始
10)、EndsWith():判斷以...結束
11)、Replace():將字符串中某個字符串替換成一個新的字符串
12)、Contains():判斷某個字符串是否包含指定的字符串
13)、Trim():去掉字符串中前後的空格
14)、TrimEnd():去掉字符串中結尾的空格
15)、TrimStart():去掉字符串中前面的空格
16)、string.IsNullOrEmpty():判斷一個字符串是否爲空或者爲null
17)、string.Join():將數組按照指定的字符串連接,返回一個字符串。
6、集合
1)、ArrayList集合
Add('...');//添加值
AddRange('...');//添加數據值
Count//集合個數屬性
Capacity//集合可包含元素的個數
注:每次集合中實際包含的元素個數(count)超過了可以包含的元素的個數(capcity)的時候,
集合就會向內存中申請多開闢一倍的空間,來保證集合的長度一直夠用。
長度可以改變,類型任意。
//創建了一個集合對象
ArrayList list = new ArrayList();
//集合:很多數據的一個集合
//數組:長度不可變、類型單一
//集合的好處:長度可以任意改變 類型隨便(函數也可)
list.Add(1);
list.Add(3.14);
list.Add(true);
list.Add("張三");
list.Add('男');
list.Add(5000m);
list.Add(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
2)、HashTable鍵值對集合
對象.Add('值');//添加值
對象.Contains('鍵');對象.ContainsKey(‘鍵’);//相同,表現如果有(‘鍵’)返回true,沒有(‘鍵’)則返回false
對象.ContainsValue('值');同上
對象.Remove('鍵');//移除指定鍵的元素
集合.Keys//鍵
集合.Valuer//值
注:在鍵值對集合當中,我們是根據鍵去找值的。
鍵值對對象[鍵]=值;
鍵值對集合當中,鍵必須是唯一的,而值是可以重複的
//創建了一個鍵值對集合對象
Hashtable ht = new Hashtable();
ht.Add(1, "張三");
ht.Add(2, true);
ht.Add(3, '男');
ht.Add(false, "錯誤的");
ht.Add(5, "張三");
ht[6] = "新來的";//這也是一種添加數據的方式
ht[1] = "把張三幹掉";
ht.Add("abc", "cba");
3)、字典集合
Dictionary<int, string> dic = new Dictionary<int, string>();
dic.Add(1, "張三");
dic.Add(2, "李四");
dic.Add(3, "王五");//新增
dic[1] = "新來的";//更新
foreach (KeyValuePair<int,string> kv in dic)//遍歷
{
Console.WriteLine("{0}---{1}",kv.Key,kv.Value);
}
//foreach (var item in dic.Keys)//遍歷;var:根據值可以推斷出變量類型;
//{
// Console.WriteLine("{0}---{1}",item,dic[item]);
//}
Hashtable和Dictionary都是.Net下的表示鍵值對的集合,那麼我們在使用中該選擇Hashtable還是Dictionary?下邊我們看看他們之間的區別:
1、Dictionary<K,V>在使用中是順序存儲的,而Hashtable由於使用的是哈希算法進行數據存儲,是無序的。
2、Dictionary的key和value是泛型存儲,Hashtable的key和value都是object
3、Dictionary是泛型存儲,不需要進行類型轉換,Hashtable由於使用object,在存儲或者讀取值時都需要進行類型轉換,所以比較耗時
4、單線程程序中推薦使用 Dictionary, 有泛型優勢, 且讀取速度較快, 容量利用更充分。多線程程序中推薦使用 Hashtable, 默認的 Hashtable 允許單線程寫入, 多線程讀取, 對 Hashtable 進一步調用 Synchronized() 方法可以獲得完全線程安全的類型. 而 Dictionary 非線程安全, 必須人爲使用 lock 語句進行保護, 效率大減。
5、在通過代碼測試的時候發現key是整數型Dictionary的效率比Hashtable快,如果key是字符串型,Dictionary的效率沒有Hashtable快。
對於如何進行選擇,個人傾向於使用Dictionary,原因是:
1、Dictionary是可排序的,Hashtable如果想排序還需要採用別的方式進行
2、Dictionary有泛型優勢,效率要高
7、list泛型
泛型(Generic) 允許您延遲編寫類或方法中的編程元素的數據類型的規範,直到實際在程序中使用它的時候。換句話說,泛型允許您編寫一個可以與任何數據類型一起工作的類或方法。
泛型(Generic)的特性
使用泛型是一種增強程序功能的技術,具體表現在以下幾個方面:
- 它有助於您最大限度地重用代碼、保護類型的安全以及提高性能。
- 您可以創建泛型集合類。.NET 框架類庫在 System.Collections.Generic 命名空間中包含了一些新的泛型集合類。您可以使用這些泛型集合類來替代 System.Collections 中的集合類。
- 您可以創建自己的泛型接口、泛型類、泛型方法、泛型事件和泛型委託。
- 您可以對泛型類進行約束以訪問特定數據類型的方法。
- 關於泛型數據類型中使用的類型的信息可在運行時通過使用反射獲取。
轉載:https://www.runoob.com/csharp/csharp-generic.html
部分函數實例:
創建泛型集合對象
List<int> list = new List<int>();
list.Add(1);//添加單個元素
list.AddRange(new int[] { 1, 2, 3, 4, 5, 6 });//添加多個元素
list.AddRange(list);
//List泛型集合可以轉換爲數組
int[] nums = list.ToArray();
裝箱、拆箱
裝箱:就是將值類型轉換爲引用類型。
拆箱:將引用類型轉換爲值類型。
看兩種類型是否發生了裝箱或者拆箱,要看,這兩種類型是否存在繼承關係。
int n = 10;
object o = n;//裝箱
int nn = (int)o;//拆箱
8、類型轉換
在c#中類型的轉換分兩種:顯式和隱式,基本的規則如下:
1、基類對象轉化爲子類對象,必須顯式轉換,規則:(類型名) 對象。
2、值類型和引用類型的轉換採用裝箱(boxing)或拆箱(unboxing).
3、子類轉化爲基類對象。
4、基本類型互相之間轉化可以用Covent類來實現。
5、字符串類型轉換爲對應的基本類型用Parse方法,除了String類型外其他的類型都可以用Parse方法。
6、用GetType可以取得對象的精確類型。
7、子類轉化爲基類,採用隱式轉換。
在進行類型轉換的時候,可以按照如下的方式進行選擇
1、Object => 已知引用類型
使用as操作符來完成
2、Object => 已知值類型
先使用is操作符來進行判斷,再用類型強轉方式進行轉換
3、已知引用類型之間轉換
首先需要相應類型提供轉換函數,再用類型強轉方式進行轉換
4、已知值類型之間轉換
最好使用系統提供的Convert類所涉及的靜態方法
(int)和Int32.Parse(),Convert.ToInt32()三者的區別
1、(int)轉換:用在數值範圍大的類型轉換成數值範圍小的類型時使用,但是如果被轉換的數值大於或者小於數值範圍,則得到一個錯誤的結果,利用這種轉換方式不能將string轉換成int,會報錯。
2、Int32.Parse()轉換:在符合數字格式的string到int類型轉換過程中使用,並可以對錯誤的string數字格式的拋出相應的異常。
3、Convert.ToInt32()轉換:使用這種轉換,所提供的字符串必須是數值的有效表達方式,該數還必須不是溢出的數。否則拋出異常。
希望本文所述對大家的C#程序設計有所幫助。
九、類
1、繼承
繼承的特性
1)、繼承的單根性:一個子類只能有一個父類。
2)、繼承的傳遞性
子類對象可以調用父類中的成員,但是父類對象永遠都只能調用自己的成員。
1)子類繼承了父類,那麼子類從父類那裏繼承過來了什麼?
首先,子類繼承了父類的屬性和方法,但是子類並沒有繼承父類的私有字段。
問題:子類有沒有繼承父類的構造函數?
答:子類並沒有繼承父類的構造函數,但是。子類會默認的調用父類無參數的構造函數,
2)創建父類對象,讓子類可以使用父類中的成員。
所以,如果在父類中重新寫了一個有參數的構造函數之後,那個無參數的就被幹掉了,
子類就調用不到了,所以子類會報錯。
解決辦法:
在父類中重新寫一個無參數的構造函數。
在子類中顯示的調用父類的構造函數,使用關鍵字:base()
里氏轉換
1)、子類可以賦值給父類
2)、如果父類中裝的是子類對象,那麼可以講這個父類強轉爲子類對象。
2、多態
首先解釋下什麼叫多態:同一操作作用於不同的對象,可以有不同的解釋,產生不同的執行結果,這就是多態性。換句話說,實際上就是同一個類型的實例調用"相同"的方法,產生的結果是不同的。這裏的"相同"打上雙引號是因爲這裏的相同的方法僅僅是看上去相同的方法,實際上它們調用的方法是不同的。
說到多態,我們不能免俗的提到下面幾個概念:重載、重寫、虛方法、抽象方法以及隱藏方法。下面就來一一介紹他們的概念。
1、重載(overload): 在同一個作用域(一般指一個類)的兩個或多個方法函數名相同,參數列表不同的方法叫做重載,它們有三個特點(俗稱兩必須一可以):
- 方法名必須相同
- 參數列表必須不相同
- 返回值類型可以不相同
public void Sleep()
{
Console.WriteLine("Animal睡覺");
}
public int Sleep(int time)
{
Console.WriteLine("Animal{0}點睡覺", time);
return time;
}
2、重寫(override):子類中爲滿足自己的需要來重複定義某個方法的不同實現,需要用 override 關鍵字,被重寫的方法必須是虛方法,用的是 virtual 關鍵字。它的特點是(三個相同):
- 相同的方法名
- 相同的參數列表
- 相同的返回值
如:父類中的定義:
public virtual void EatFood()
{
Console.WriteLine("Animal吃東西");
}
子類中的定義:
public override void EatFood()
{
Console.WriteLine("Cat吃東西");
//base.EatFood();
}
小提示:經常有童鞋問重載和重寫的區別,而且網絡上把這兩個的區別作爲 C# 做常考的面試題之一。實際上這兩個概念完全沒有關係,僅僅都帶有一個"重"字。他們沒有在一起比較的意義,僅僅分辨它們不同的定義就好了。
3、虛方法:即爲基類中定義的允許在派生類中重寫的方法,使用virtual關鍵字定義。如:
public virtual void EatFood()
{
Console.WriteLine("Animal吃東西");
}
就是將父類的方法標記爲虛方法 ,使用關鍵字 virtual,這個函數可以被子類重新寫一個遍。
繼承的子類可以用override 可重寫子類方法。
public class Person
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
public Person(string name)
{
this.Name = name;
}
public virtual void SayHello()//虛方法
{
Console.WriteLine("我是人類");
}
}
public class Chinese : Person
{
public Chinese(string name)
: base(name)
{
}
public override void SayHello()//重寫
{
Console.WriteLine("我是中國人,我叫{0}", this.Name);
}
}
注意:虛方法也可以被直接調用。如:
Animal a = new Animal();
a.EatFood();
執行輸出結果爲:
Animal吃東西
4、抽象方法:在基類中定義的並且必須在派生類中重寫的方法,使用 abstract 關鍵字定義。如:
public abstract class Biology
{
public abstract void Live();
}
public class Animal : Biology
{
public override void Live()
{
Console.WriteLine("Animal重寫的抽象方法");
//throw new NotImplementedException();
}
}
注意:抽象方法只能在抽象類中定義,如果不在抽象類中定義,則會報出如下錯誤:
虛方法和抽象方法的區別是:因爲抽象類無法實例化,所以抽象方法沒有辦法被調用,也就是說抽象方法永遠不可能被實現。
5、隱藏方法:在派生類中定義的和基類中的某個方法同名的方法,使用 new 關鍵字定義。如在基類 Animal 中有一方法 Sleep():
public void Sleep()
{
Console.WriteLine("Animal Sleep");
}
則在派生類 Cat 中定義隱藏方法的代碼爲:
new public void Sleep()
{
Console.WriteLine("Cat Sleep");
}
或者爲:
public new void Sleep()
{
Console.WriteLine("Cat Sleep");
}
注意:
- (1)隱藏方法不但可以隱藏基類中的虛方法,而且也可以隱藏基類中的非虛方法。
- (2)隱藏方法中父類的實例調用父類的方法,子類的實例調用子類的方法。
- (3)和上一條對比:重寫方法中子類的變量調用子類重寫的方法,父類的變量要看這個父類引用的是子類的實例還是本身的實例,如果引用的是父類的實例那麼調用基類的方法,如果引用的是派生類的實例則調用派生類的方法。
(以上)轉載自:https://www.runoob.com/w3cnote/csharp-polymorphism2.html
1)、partial部分類
使用partial關鍵字可以聲明部分類, 部分類的作用是可以在多個文件中聲明同一個類, 主要用於類比較大的時候進行拆分,或者xaml中使用也比較多。
public partial class Person
{
private string _name;
public void Test()
{
}
}
public partial class Person
{
public void Test(string name)
{
}
}
不要把部分類以爲是定義了多個類,其實還是一個類,只是把這個類拆分了。 在程序運行的時候編譯器會把這個類合併在一起的, 這樣做的好處是,當你有一個類很大的時候你可以按實現功能拆分在不同的文件中,這樣就方便閱讀和修改了。
2)、sealed密封類
不能夠被其他類繼承,但是可以繼承於其他類。
密封類可以用來限制擴展性,如果密封了某個類,則其他類不能從該類繼承;如果密封了某個成員,則派生類不能重寫該成員的實現。默認情況下,不應密封類型和成員。密封可以防止對庫的類型和成員進行自定義,但也會影響某些開發人員對可用性的認識。
C#中使用密封類時,如果類滿足如下條件,則應將其密封。
類是靜態類。
類包含帶有安全敏感信息的繼承的受保護成員。
類繼承多個虛成員,並且密封每個成員的開發和測試開銷明顯大於密封整個類。
類是一個要求使用反射進行快速搜索的屬性。密封屬性可提高反射在檢索屬性時的性能。
訪問修飾符 sealed class 類名:
基類或接口
{
//類成員
}
- 說明:① 密封類不能作爲基類被繼承,但它可以繼承別的類或接口。
- ② 在密封類中不能聲明受保護成員或虛成員,因爲受保護成員只能從派生類進行訪問,而虛成員只能在派生類中重寫。
- ③ 由於密封類的不可繼承性,因此密封類不能聲明爲抽象的,即sealed修飾符不能與abstract修飾符同時使用。
轉載:https://www.cnblogs.com/bdqnquliang/p/6664294.html
3)接口
接口定義了所有類繼承接口時應遵循的語法合同。接口定義了語法合同 "是什麼" 部分,派生類定義了語法合同 "怎麼做" 部分。
接口定義了屬性、方法和事件,這些都是接口的成員。接口只包含了成員的聲明。成員的定義是派生類的責任。接口提供了派生類應遵循的標準結構。
接口使得實現接口的類或結構在形式上保持一致。
抽象類在某種程度上與接口類似,但是,它們大多隻是用在當只有少數方法由基類聲明由派生類實現時。
[public] interface I..able
{
成員;
}
接口的實現與類的繼承語法格式類似:
class InterfaceImplementer : IMyInterface
以下實例定義了兩個接口 IMyInterface 和 IParentInterface。
如果一個接口繼承其他接口,那麼實現類或結構就需要實現所有接口的成員。
以下實例 IMyInterface 繼承了 IParentInterface 接口,因此接口實現類必須實現 MethodToImplement() 和 ParentInterfaceMethod() 方法:
using System;
interface IParentInterface
{
void ParentInterfaceMethod();
}
interface IMyInterface : IParentInterface
{
void MethodToImplement();
}
class InterfaceImplementer : IMyInterface
{
static void Main()
{
InterfaceImplementer iImp = new InterfaceImplementer();
iImp.MethodToImplement();
iImp.ParentInterfaceMethod();
}
public void MethodToImplement()
{
Console.WriteLine("MethodToImplement() called.");
}
public void ParentInterfaceMethod()
{
Console.WriteLine("ParentInterfaceMethod() called.");
}
}
實例輸出結果爲:
MethodToImplement() called.
ParentInterfaceMethod() called.
注意:
- 接口方法不能用public abstract等修飾。接口內不能有字段變量,構造函數。(默認是public)
- 接口內可以定義屬性(有get和set的方法)。如string color { get ; set ; }這種。
- 實現接口時,必須和接口的格式一致。
- 必須實現接口的所有方法。
接口語法解讀:
- 接口是一種規範;
- 只要一個類繼承了一個接口,這個類就必須實現這個接口中所有的成員;
- 爲了多態。 接口不能被實例化;
- 也就是說,接口不能new(不能創建對象)
- 接口中的成員不能加“訪問修飾符”,接口中的成員訪問修飾符爲public,不能修改。
- (接口裏默認爲public) 接口中的成員不能有任何實現(“光說不做”,只是定義了一組未實現的成員)。(類中默認爲private )
- 接口中只能有方法、屬性、索引器、事件,不能有“字段”和構造函數。
- 接口與接口之間可以繼承,並且可以多繼承。
- 接口並不能去繼承一個類,而類可以繼承接口 (接口只能繼承於接口,而類既可以繼承接口,也可以繼承類)
- 實現接口的子類必須實現該接口的全部成員。
- 一個類可以同時繼承一個類並實現多個接口,如果一個子類同時繼承了父類A,並實現了接口IA,那麼語法上A必須寫在IA的前面。
- class MyClass:A,IA{},因爲類是單繼承的。
顯示實現接口的目的:解決方法的重名問題
什麼時候顯示的去實現接口:
當繼承的藉口中的方法和參數一摸一樣的時候,要是用顯示的實現接口
class Program
{
static void Main(string[] args)
{
//顯示實現接口就是爲了解決方法的重名問題
IFlyable fly = new Bird();
fly.Fly();
Bird bird = new Bird();
bird.Fly();
Console.ReadKey();
}
}
public class Bird : IFlyable
{
public void Fly()
{
Console.WriteLine("鳥飛會");
}
/// <summary>
/// 顯示實現接口
/// </summary>
void IFlyable.Fly()
{
Console.WriteLine("我是接口的飛");
}
部分轉載:https://www.runoob.com/csharp/csharp-interface.html
十、命名空間
可以認爲類是屬於命名空間的。
如果在當前項目中沒有這個類的命名空間,需要我們手動的導入這個類所在的
命名空間。
1)、用鼠標去點
2)、alt+shift+F10
3)、記住命名空間,手動的去引用
在一個項目中引用另一個項目的類
1)、添加引用(選中項目——>右鍵——>添加引用)
2)、引用命名空間(例:using 類的namespace)
十一、部分實用函數使用
1、計算程序運行時間
Stopwatch sw = new Stopwatch();
sw.Start();//開始
foreach (var item in nums)
{
}
sw.Stop();//結束
Console.WriteLine(sw.Elapsed);//輸出運行時間
2、重寫父類的ToStrong()
public class Person
{
public override string ToString()
{
return "Hello World";
}
}
3、foreach循環
例:
foreach (var item in collection)//var:根據值可以推斷出變量類型;item集合每一個元素;in在...裏;collection集合
{
}
foreach (var item in hast.Keys)
{
Console.WriteLine("{0},{1}", hast[item], item);
}
Console.Read();
十二、常用關鍵字解析
1、is、as
C#中的is
檢查一個對象是否兼容於其他指定的類型,並返回一個Bool值,如果一個對象是某個類型或是其父類型的話就返回爲true,否則的話就會返回爲false。永遠不會拋出異常
如果對象引用爲null,那麼is操作符總是返回爲false,因爲沒有對象可以檢查其類型。
例如
代碼如下:
object o = new object();
if (o is Label)
{
Label lb = (Label)o;
Response.Write("類型轉換成功");
}
else
{
Response.Write("類型轉換失敗");
}
C#中as的轉換規則
1、檢查對象類型的兼容性,並返回轉換結果,如果不兼容則返回null;
2、不會拋出異常;
3、如果結果判斷爲空,則強制執行類型轉換將拋出NullReferenceException異常;
4、用as來進行類型轉換的時候,所要轉換的對象類型必須是目標類型或者轉換目標類型的派生類型
例如
代碼如下:
object o = new object();
Label lb = o as Label;
if (lb == null)
{
Response.Write("類型轉換失敗");
}
else
{
Response.Write("類型轉換成功");
}
使用as操作符有如下幾點限制
第一個就是,不用在類型之間進行類型轉化,即如下編寫就會出現編譯錯誤。
代碼如下:
NewType newValue = new NewType();
NewType1 newValue = newValue as NewType1;
第二個就是,不能應用在值類型數據,即不能如下寫(也會出現編譯錯誤)。
代碼如下:
object objTest = 11;
int nValue = objTest as int;
as與is的區別
1、AS在轉換的同事兼判斷兼容性,如果無法進行轉換,則 as 返回 null(沒有產生新的對象)而不是引發異常。有了AS我想以後就不要再用try-catch來做類型轉換的判斷了。因此as轉換成功要判斷是否爲null。
2、AS是引用類型類型的轉換或者裝箱轉換,不能用與值類型的轉換。如果是值類型只能結合is來強制轉換
3、IS只是做類型兼容判斷,並不執行真正的類型轉換。返回true或false,不會返回null,對象爲null也會返回false。
4、AS模式的效率要比IS模式的高,因爲藉助IS進行類型轉換的化,需要執行兩次類型兼容檢查。而AS只需要做一次類型兼容,一次null檢查,null檢查要比類型兼容檢查快。
2、base和this
base:
用於在派生類中實現對基類公有或者受保護成員的訪問,但是隻侷限在構造函數、實例方法和實例屬性訪問器中。
MSDN中小結的具體功能包括:
(1)調用基類上已被其他方法重寫的方法。
(2)指定創建派生類實例時應調用的基類構造函數。
base常用於,在派生類對象初始化時和基類進行通信。
base可以訪問基類的公有成員和受保護成員,私有成員是不可訪問的。
在多層繼承中,base可以指向的父類的方法有兩種情況:一是有重載存在的情況下,base將指向直接繼承的父類成員的方法;而沒有重載存在的情況下,base可以指向任何上級父類的公有或者受保護方法。
this:
1)、代表當前類的對象
2)、在類當中顯示的調用本類的構造函數 :this
用於引用類的當前實例,也包括繼承而來的方法,通常可以隱藏this。
MSDN中的小結功能主要包括:
(1)限定被相似的名稱隱藏的成員
(2)將對象作爲參數傳遞到其他方法
(3)聲明索引器
this指代類對象本身,用於訪問本類的所有常量、字段、屬性和方法成員,而且不管訪問元素是任何訪問級別。因爲,this僅僅侷限於對象內部,對象外部是無法看到的,這就是this的基本思想。另外,靜態成員不是對象的一部分,因此不能在靜態方法中引用this。
通用規則:
1、儘量少用或者不用base和this。除了避開子類的名稱衝突和在一個構造函數中調用其他的構造函數之外,base和this的使用容易引起不必要的結果。
2、在靜態成員中使用base和this都是不允許的。原因是,base和this訪問的都是類的實例,也就是對象,而靜態成員只能由類來訪問,不能由對象來訪問。
3、base是爲了實現多態而設計的。
4、使用this或base關鍵字只能指定一個構造函數,也就是說不可同時將this和base作用在一個構造函數上。
5、簡單的來說,base用於在派生類中訪問重寫的基類成員;而this用於訪問本類的成員,當然也包括繼承而來公有和保護成員。
6、除了base,訪問基類成員的另外一種方式是:顯示的類型轉換來實現。只是該方法不能爲靜態方法。
base調用構造方法
public class BaseClass
{
public BaseClass()
{
Console.WriteLine("調用基類--無參數的構造函數");
}
public BaseClass(string name)
{
Console.WriteLine("調用基類--有參數的構造函數");
}
}
public class DerivedClass:BaseClass
{
public DerivedClass()
: base()
{
}
public DerivedClass(string name)
: base(name)
{
}
static void Main()
{
DerivedClass a = new DerivedClass();//調用基類--無參數的構造函數
DerivedClass b = new DerivedClass("Andy");//調用基類--有參數的構造函數
Console.ReadLine();
}
}
base在派生類中調用基類的方法
public class BaseClass
{
public virtual void GetInfo()
{
Console.WriteLine("Andy.");
}
}
public class DerivedClass :BaseClass
{
public override void GetInfo()
{
base.GetInfo();//調用基類的方法,顯示Andy.
Console.WriteLine("Chen");//顯示Andy.Chen
}
}
base和this的綜合使用
public class MyBaseClass
{
public MyBaseClass()
{
Console.Write("調用父類無參數的構造函數");
}
public MyBaseClass(int i)
{
Console.Write("調用父類一個參數的構造函數");
}
}
public class MyDerivedClass : MyBaseClass
{
public int age;
public static int age2;//只要類裏存在靜態變量,那麼靜態變量總是最先初始化的。
//靜態構造函數只執行一次
static MyDerivedClass() //既然要初始化靜態變量,就要調用靜態的構造函數。
{
age2 = 100;
Console.Write(age2);
}
public MyDerivedClass()
: this(5)//調用當前實例有參數的構造函數。如果只調用這個構造函數,那還需要調用一次基類沒有參的構造函數!!!
{
age = 101;
Console.WriteLine(age);
}
public MyDerivedClass(int i) : base(i)//調用基類有參數的構造函數
{
age = 102;
Console.WriteLine(age);
}
public MyDerivedClass(int i, int j)
{
Console.WriteLine("兩個變量的參數");
}
}
class Program
{
static void Main(string[] args)
{
MyDerivedClass myder = new MyDerivedClass(); //輸出100 ,"調用父類無參數的構造函數",101
//執行順序:<1>: static MyDerivedClass() <2>: public MyBaseClass() <3>:public MyDerivedClass()
//---------------------------------------------------------------------------------------------
MyDerivedClass myder2 = new MyDerivedClass(5); //輸出"調用父類無參數的構造函數",102。
//在初始化myder對象的時候已經初始化過靜態變量age2了。因爲靜態構造函數最多執行一次,所以初始化myder2對象的時候就不會在繼續初始化靜態變量age2了
//執行順序:<1>: public MyBaseClass() <2>: public MyDerivedClass(int i)
//假如我想在初始化myder2對象的時候調用父類帶有一個參數的構造函數怎麼辦呢?很好辦只要在派生類的構造函數後面加一個:base(i)
/* base 關鍵字用於從派生類中訪問基類的成員;指定創建派生類實例時應調用的基類構造函數。
public MyDerivedClass(int i):base(i)
{
age = 102;
Console.WriteLine(age);
}
執行順序:<1>: public MyBaseClass(int i) <2>: public MyDerivedClass(int i)
顧這裏輸出的是 "調用父類一個參數的構造函數",102
*/
//---------------------------------------------------------------------------------------------
MyDerivedClass myder3 = new MyDerivedClass(5, 6); //輸出"調用父類無參數的構造函數","兩個變量的參數"
//執行順序:<1>: public MyBaseClass() <2>: public MyDerivedClass(int i, int j)
Console.ReadKey();
}
}
3、using
using 關鍵字有兩個主要用途:
(一).作爲指令,用於爲命名空間創建別名或導入其他命名空間中定義的類型。
(二).作爲語句,用於定義一個範圍,在此範圍的末尾將釋放對象。
1)using指令
①允許在命名空間中使用類型,這樣,您就不必在該命名空間中限定某個類型的使用:
using System.Text;
using PC.Company;
②爲命名空間或類型創建別名。
using MyCompany = PC.Company; //命名空間的別名。
using Project = PC.Company.Project; //類型的別名
using引入命名空間,並不等於編譯器編譯時加載該命名空間所在的程序集,程序集的加載決定於程序中對該程序集是否存在調用操作,如果代碼中不存在任何調用操作則編譯器將不會加載using引入命名空間所在程序集。因此,在源文件開頭,引入多個命名空間,並非加載多個程序集,不會造成“過度引用”的弊端。
創建別名的另一個重要的原因在於同一文件中引入的不同命名空間中包括了相同名稱的類型,如SharpMap.Geometries.Point與System.Drawing.Point。爲了避免出現名稱衝突,可以通過設定別名來解決:
using SGPoint = SharpMap.Geometries.Point;
using SDPoint = System.Drawing.Point;
儘管我們可以通過類型全名稱來加以區分,但是這顯然不是最佳的解決方案。用using指令創建別名,有效的解決了這種可能的命名衝突,纔是最佳的解決方案。
2)using語句
using 語句允許程序員指定使用資源的對象應當何時釋放資源。using 語句中使用的對象必須實現 IDisposable 接口。此接口提供了 Dispose 方法,該方法將釋放此對象的資源。
①可以在 using 語句之中聲明對象。
Font font2 = new Font("Arial", 10.0f);
using (font2)
{
// use font2
}
②可以在 using 語句之前聲明對象。
using (Font font2 = new Font("Arial", 10.0f))
{
// use font2
}
③可以有多個對象與 using 語句一起使用,但是必須在 using 語句內部聲明這些對象。
using (Font font3=new Font("Arial",10.0f), font4=new Font("Arial",10.0f))
{
// Use font3 and font4.
}
使用規則
①using只能用於實現了IDisposable接口的類型,禁止爲不支持IDisposable接口的類型使用using語句,否則會出現編譯錯誤;
②using語句適用於清理單個非託管資源的情況,而多個非託管對象的清理最好以try-finnaly來實現,因爲嵌套的using語句可能存在隱藏的Bug。內層using塊引發異常時,將不能釋放外層using塊的對象資源;
③using語句支持初始化多個變量,但前提是這些變量的類型必須相同,例如:
using(Pen p1 = new Pen(Brushes.Black), p2 = new Pen(Brushes.Blue))
{
//
}
④針對初始化對個不同類型的變量時,可以都聲明爲IDisposable類型,例如:
using (IDisposable font = new Font("Verdana", 12), pen = new Pen(Brushes.Black))
{
float size = (font as Font).Size;
Brush brush = (pen as Pen).Brush;
}
using實質
在程序編譯階段,編譯器會自動將using語句生成爲try-finally語句,並在finally塊中調用對象的Dispose方法,來清理資源。所以,using語句等效於try-finally語句,例如:
Font f2 = new Font("Arial", 10, FontStyle.Bold);
try
{
//執行文本繪製操作
}
finally
{
if (f2 != null) ((IDisposable)f2).Dispose();
}
轉載:https://blog.csdn.net/WanderOCN/article/details/6659811
十三、文件操作
1、使用FileStream來讀寫文件
System.IO 命名空間中的 FileStream 類有助於文件的讀寫與關閉。該類派生自抽象類 Stream。
您需要創建一個 FileStream 對象來創建一個新的文件,或打開一個已有的文件。創建 FileStream 對象的語法如下:
FileStream <object_name> = new FileStream( <file_name>,
<FileMode Enumerator>, <FileAccess Enumerator>, <FileShare Enumerator>);
例如,創建一個 FileStream 對象 F 來讀取名爲 sample.txt 的文件:
FileStream F = new FileStream("sample.txt", FileMode.Open, FileAccess.Read, FileShare.Read);//參數:路徑,打開(無此文件報錯),讀取,允許隨後打開文件讀取
讀取txt文件整個過程:
讀小txt文件:
FileStream fsRead = new FileStream(@"C:\Users\SpringRain\Desktop\new.txt", FileMode.OpenOrCreate, FileAccess.Read);//參數:文件地址,打開文件(沒有文件則創建),讀取
byte[] buffer = new byte[1024 * 1024 * 5];//字節數組5M
//返回本次實際讀取到的有效字節數
int r = fsRead.Read(buffer, 0, buffer.Length);//參數:每次讀取文件流的大小,開始位置,最多讀取的長度
//將字節數組中每一個元素按照指定的編碼格式解碼成字符串
string s = Encoding.UTF8.GetString(buffer, 0, r);//參數:字節,第一個要解碼字節的索引,要解碼的字節數
//關閉流
fsRead.Close();
//釋放流所佔用的資源
fsRead.Dispose();
讀大文件:
注:將創建文件流對象的過程寫在using當中,會自動的幫助我們釋放流所佔用的資源。
txt文件寫入:
using (FileStream fsWrite = new FileStream(@"C:\Users\SpringRain\Desktop\new.txt", FileMode.OpenOrCreate, FileAccess.Write))
{
string str = "看我遊牧又把你覆蓋掉";
byte[] buffer = Encoding.UTF8.GetBytes(str);
fsWrite.Write(buffer, 0, buffer.Length);//參數:字節數組,開始位置,長度
}
Console.WriteLine("寫入OK");
Console.ReadKey();
多媒體文件的複製:
static void Main(string[] args)
{
//思路:就是先將要複製的多媒體文件讀取出來,然後再寫入到你指定的位置
string source = @"C:\Users\SpringRain\Desktop\1、複習.wmv";//讀取位置
string target = @"C:\Users\SpringRain\Desktop\new.wmv";//複製目的位置
CopyFile(source, target);
Console.WriteLine("複製成功");
Console.ReadKey();
}
public static void CopyFile(string soucre, string target)
{
//1、我們創建一個負責讀取的流
using (FileStream fsRead = new FileStream(soucre, FileMode.Open, FileAccess.Read))
{
//2、創建一個負責寫入的流
using (FileStream fsWrite = new FileStream(target, FileMode.OpenOrCreate, FileAccess.Write))
{
byte[] buffer = new byte[1024 * 1024 * 5];
//因爲文件可能會比較大,所以我們在讀取的時候 應該通過一個循環去讀取
while (true)
{
//返回本次讀取實際讀取到的字節數
int r = fsRead.Read(buffer, 0, buffer.Length);
//如果返回一個0,也就意味什麼都沒有讀取到,讀取完了
if (r == 0)
{
break;
}
fsWrite.Write(buffer, 0, r);
}
}
}
StreamReader和StreamWriter:
//使用StreamReader來讀取一個文本文件
using (StreamReader sr = new StreamReader(@"C:\Users\SpringRain\Desktop\抽象類特點.txt",Encoding.Default))
{
while (!sr.EndOfStream)
{
Console.WriteLine(sr.ReadLine());//每次讀一行
}
}
//使用StreamWriter來寫入一個文本文件
using (StreamWriter sw = new StreamWriter(@"C:\Users\SpringRain\Desktop\newnew.txt",true))//true表示追加
{
sw.Write("看我有木有把你覆蓋掉");
}
FileStream 操作字節的
StreamReader和StreamWriter 操作字符的(操作文本的)
部分轉載:https://www.runoob.com/csharp/csharp-file-io.html
2、path類
①Path類是static類型
②常用方法
Path.GetFullPath(file) 取全路徑
Path.GetFileName(file) 取文件名,包含擴展名
Path.GetFileNameWithoutExtension(file) 取文件名,不包含擴展名
Path.GetExtension(file) 取擴展名
Path.GetDirectoryName(file) 取路徑名
Path.GetPathRoot(file) 取盤符
Path.Combine(file1,file2) 合併2個路徑
③注意事項
a.使用前需要對參數進行判空,其次追加try catch來捕獲Exception。
string fullpath7 = null;
if (!String.IsNullOrWhiteSpace(file))
{
try
{
fullpath7 = Path.GetFullPath(file);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
b.GetFullPath()可以將多個 / \ 合併爲1個,使之格式化爲合法的路徑。末尾的\會保留。
c.GetDirectoryName()結果末尾沒有\。
d.Combine() 不會合並多個 / \ ,第二個參數不能以/ \ 開頭。
e.利用GetDirectoryName()和Combine()去掉末尾\.
string dir2 = Path.GetDirectoryName(Path.Combine(@"D:\1","Temp")); // D:\1
string dir3 = Path.GetDirectoryName(Path.Combine(@"D:\1\", "Temp")); // D:\1
public static void TestPath()
{
string file = "App.config"; //c:\users\qqq\source\repos\StudyDesignMode\StudyDesignMode\bin\Debug\App.config
/* 正常用法 */
//取完整路徑
string fullpath = Path.GetFullPath(file); //c:\users\qqq\source\repos\StudyDesignMode\StudyDesignMode\bin\Debug\App.config
//取文件名
string name = Path.GetFileName(@"D:\1\2\App.config"); //App.config
//取擴展名
string extension = Path.GetExtension(@"D:\1\2\App.config"); //.config
//取文件名 不帶擴展名
string nameWithoutExtension = Path.GetFileNameWithoutExtension(@"D:\1\2\App.config"); //App
//取所在文件夾
string dir = Path.GetDirectoryName(@"D:\1\2\App.config"); //D:\1\2
//取所在磁盤
string root = Path.GetPathRoot(@"D:\1\2\App.config"); //D:\
//連接路徑
string combine = Path.Combine(@"1", @"2"); // 1\2
/* 異常用法 */
//參數爲null
//string fullpath1 = Path.GetFullPath(null); //Exception
//參數爲空字符串
//string fullpath2 = Path.GetFullPath(""); //Exception
string fullpath3 = Path.GetFullPath(@"D:\\//\\//dfjk\\\\1///2\/\/\/\/\/3\"); //D:\dfjk\1\2\3\ 忽略了多個 / \ 爲1個 \ 。保留了末尾的 \ 。
//無擴展名
string name1 = Path.GetFileName(@"D:\1\2\App"); //App
//只有擴展名
string name2 = Path.GetFileName(@"D:\1\2\.config"); //.config
//無文件名
string name3 = Path.GetFileName(@"D:\1\2\"); // ""
//只有盤符
string name4 = Path.GetFileName(@"D:"); // ""
//參數爲null
string name5 = Path.GetFileName(null); // null
//參數爲""
string name6 = Path.GetFileName(""); // ""
//無擴展名
string extension1 = Path.GetExtension(@"D:\1\2\App"); //""
//只有擴展名
string extension2 = Path.GetExtension(@"D:\1\2\.config"); //.config
//無文件名
string extension3 = Path.GetExtension(@"D:\1\2\"); // ""
//只有盤符
string extension4 = Path.GetExtension(@"D:"); // ""
//參數爲null
string extension5 = Path.GetExtension(null); // null
//參數爲""
string extension6 = Path.GetExtension(""); // ""
//參數爲null
//string combine1 = Path.Combine(null,null); // Exception
//string combine2 = Path.Combine("", null); // Exception
//參數爲""
string combine3 = Path.Combine("", ""); // ""
//多個/ \
string combine4 = Path.Combine(@"///1\\\2\3", @"4"); // ///1\\\2\3\4
//第二個參數以/開頭
string combine5 = Path.Combine(@"///1\\\2\3", @"/4"); // /4
//第二個參數以\開頭
string combine6 = Path.Combine(@"///1\\\2\3", @"\4"); // \4
//第一個參數以\結尾
string combine7 = Path.Combine(@"///1\\\2\3\\", @"4"); // ///1\\\2\3\\4
//第一個參數以/結尾
string combine8 = Path.Combine(@"///1\\\2\3/", @"4"); // ///1\\\2\3/4
//第二個參數以/開頭
string combine9 = Path.Combine(@"///1\\\2\3\", @"/4"); // /4
//第二個參數以\開頭
string combine10 = Path.Combine(@"///1\\\2\3\", @"\4"); // \4
//取所在文件夾
string dir1 = Path.GetDirectoryName(@"D:\1\2\"); //D:\1\2
string dir2 = Path.GetDirectoryName(Path.Combine(@"D:\1","Temp")); // D:\1
string dir3 = Path.GetDirectoryName(Path.Combine(@"D:\1\", "Temp")); // D:\1
}
string dir4 = Path.GetDirectoryName(@"\\192.168.0.2\share\file_1.txt"); // \\192.168.0.2\share
string root1 = Path.GetPathRoot(@"\\192.168.0.2\share\file_1.txt"); // \\192.168.0.2\share
string root2 = Path.GetPathRoot(@"192.168.0.2\share\file_1.txt"); // ""
string root3 = Path.GetPathRoot(@"//192.168.0.2\share\file_1.txt"); // \\192.168.0.2\share
string root4 = Path.GetPathRoot(@"//192.168.0.2\share\1\2file_1.txt"); // \\192.168.0.2\share
3、Flie類
File類,是一個靜態類,主要是來提供一些函數庫用的。靜態實用類,提供了很多靜態的方法,支持對文件的基本操作,包括創建,拷貝,移動,刪除和打開一個文件。File類方法的參量很多時候都是路徑path。File的一些方法可以返回FileStream和StreamWriter的對象。可以和他們配套使用。
System.IO.File類和System.IO.FileInfo類主要提供有關文件的各種操作,在使用時需要引用System.IO命名空間。下面通過程序實例來介紹其主要屬性和方法。
File類常用的操作方法
1)、創建文件方法
//參數1:要創建的文件路徑
File.Create(@"D:\Test\Debug1\測試.txt")
2)、打開文件方法
//參數1:要打開的文件路徑,參數2:打開的文件方式
File.Open(@"D:\Test\Debug1\測試.txt",FileMode.Append)
3)、追加文件方法
//參數1:要追加的文件路徑,參數2:追加的內容
File.AppendAllText(@"D:\Test\Debug1\測試.txt","哈哈");
4)、複製文件方法
//參數1:要複製的源文件路徑,參數2:複製後的目標文件路徑,參數3:是否覆蓋相同文件名
File.Copy(@"D:\Test\Debug1\測試.txt", @"D:\Test\Debug2\測試1.txt", true);
5)、移動文件方法
//參數1:要移動的源文件路徑,參數2:移動後的目標文件路徑
File.Move(@"D:\Test\Debug1\測試.txt", @"D:\Test\Debug3\測試2.txt");
6)、刪除文件方法(徹底刪除)
//參數1:要刪除的文件路徑
File.Delete(@"D:\Test\Debug1\測試.txt");
7)、設置文件屬性方法
//參數1:要設置屬性的文件路徑,參數2:設置的屬性類型(只讀、隱藏等)
File.SetAttributes(@"D:\Test\Debug1\測試.txt", FileAttributes.Hidden);
編碼
常見編碼
(1)、通用字符集(UCS)
ISO/IEC 10646-1 [ISO-10646]定義了一種多於8比特字節的字符集,稱作通用字符集(UCS),它包含了世界上大多數可書寫的字符系統。已定義了兩種多8比特字節編碼,對每一個字符采用四個8比特字節編碼的稱爲UCS-4,對每一個字符采用兩個8比特字節編碼的稱爲UCS-2。它們僅能夠對UCS的前64K字符進行編址,超出此範圍的其它部分當前還沒有分配編址。
(2)、基本多語言面(BMP)
ISO 10646 定義了一個31位的字符集。然而,在這巨大的編碼空間中,迄今爲止只分配了前65534個碼位 (0x0000 到0xFFFD)。這個UCS的16位子集稱爲 “基本多語言面 ”(Basic Multilingual Plane, BMP)。
(3)、Unicode編碼
歷史上,有兩個獨立的,創立單一字符集的嘗試。一個是國際標準化組織(ISO)的 ISO 10646 項目;另一個是由(一開始大多是美國的)多語言軟件製造商組成的協會組織的 Unicode 項目。幸運的是, 1991年前後, 兩個項目的參與者都認識到:世界不需要兩個不同的單一字符集。它們合併雙方的工作成果,併爲創立一個單一編碼表而協同工作。兩個項目仍都存在並獨立地公佈各自的標準,但 Unicode 協會和 ISO/IEC JTC1/SC2 都同意保持 Unicode 和 ISO 10646 標準的碼錶兼容,並緊密地共同調整任何未來的擴展。Unicode 標準額外定義了許多與字符有關的語義符號學,一般而言是對於實現高質量的印刷出版系統的更好的參考。
(4)、UTF-8編碼
特性:
1)UTF-8向UCS-4,UCS-2兩者中任一個進行相互轉換比較容易。
2)多8比特字節序列的第一個8比特字節指明瞭系列中8比特字節的數目。
3)8比特字節值FE和FF永遠不會出現。
4)在8比特字符流中字符邊界從哪裏開始較容易發現。
(5)、UTF-7編碼
UTF-7:A Mail-Safe Transformation Format of Unicode(RFC1642)。這是一種使用 7 位 ASCII 碼對 Unicode 碼進行轉換的編碼。它的設計目的仍然是爲了在只能傳遞 7 爲編碼的郵件網關中傳遞信息。 UTF-7 對英語字母、數字和常見符號直接顯示,而對其他符號用修正的 Base64 編碼。符號 + 和 - 號控制編碼過程的開始和暫停。所以亂碼中如果夾有英文單詞,並且相伴有 + 號和 - 號,這就有可能是 UTF-7 編碼。
(6)GB2312編碼
最早,表示漢字的區位碼中,分爲94個區,每個區94個漢字,1-15區是西文字符,圖形等,16-5爲一級漢字,56-87爲二級漢字,87區以上爲新字用。而我們在Windows默認的編碼,GB2312(1981年國家頒佈的《信息交換用漢字編碼字符集基本集》)
字符串的編碼轉換:
string str = "abcd";//測試字符串
byte[] bytes = Encoding.GetEncoding("ascii").GetBytes(str);//將字符串轉成ascii編碼的字節數組,這裏的bytes數組,長度爲4,分別對應於abcd的ascii碼97、98、99、100
string result = Encoding.GetEncoding("ascii").GetString(bytes);//將字節數組轉回爲字符串
Console.WriteLine(result);//輸出abcd
注:這裏應用到了ascii編碼。我們知道,ascii碼是國際標準編碼,全稱爲:美國信息交換標準編碼,只能表示127個字符,不能代表漢字,所以我們對漢字進行ascii編碼之後,是不能進行還原的。漢字不能轉變爲ascii碼,因此會變成亂碼,對亂碼進行還原也就還原不了了。正是由於ascii碼的侷限性,不能表示世界上各種語言和符號,因此ISO(國際標準化組織)推出了unicode編碼,它可以容納世界上所有的文字和字符。
有些時候,可能編碼會是這樣子的:\u4e2d\u56fd
而我們可以這樣來處理:如下
string value = "\u4e2d\u56fd";
Console.WriteLine(Uri.UnescapeDataString(value));//輸出:中國
項目開發中經常會有出現亂碼的情況,這就是由於兩端(服務端、請求端)編解碼的方式不一致造成的。比如服務端是utf-8編碼,而在客戶端以gbk接收,那麼就會出現亂碼。所以解決亂碼這個問題,思路就是從對方的編碼方式入手,弄清楚對方的編碼是什麼編碼,我這邊就以什麼編碼來解碼。這個解決問題的思路,在我實際項目開發過程中屢試不爽。
比如我們經常會用到web頁面導出excel的問題。代碼如下:
string fileName = HttpUtility.UrlEncode("Excel文件名爲中文哦.xls");
Response.Clear();
Response.Buffer = true;
Response.AppendHeader("Content-Disposition", "attachment;filename=" + fileName);
Response.ContentEncoding = System.Text.Encoding.UTF8;
Response.ContentType = "application/vnd.ms-excel";
this.EnableViewState = false;
經過HttpUtility.UrlEncode方法進行編碼之後,在IE瀏覽器下彈出的excel下載對話框中顯示的文件名就不會顯示亂碼,而顯示正常的漢字了。對應的方法是HttpUtility.UrlDecode方法,進行解密。這兩個方法在web開發編解碼當中會用到。
比如:
string text = "http://www.baidu.com/baidu?word=%D6%D0%B9%FA%B4%F3%B0%D9%BF%C6%D4%DA%CF%DF%C8%AB%CE%C4%BC%EC%CB%F7&tn=myie2dg";
string result = HttpUtility.UrlDecode(text, Encoding.GetEncoding("gbk"));
Response.Write(result);//輸出http://www.baidu.com/baidu?word=中國大百科在線全文檢索&tn=myie2dg
字符串存入txt文件如下:
//沒有這個文件的話 會給你創建一個 有的話 會給你覆蓋掉
string str="今天天氣好晴朗處處好風光";
//需要將字符串轉換成字節數組
byte[] buffer= Encoding.Default.GetBytes(str);
File.WriteAllBytes(@"C:\Users\SpringRain\Desktop\new.txt", buffer);
txt文件以行的形式讀取:
string[] contents = File.ReadAllLines(@"C:\Users\SpringRain\Desktop\抽象類特點.txt", Encoding.Default);//所謂Encoding.Default,是指當前系統設置的“默認字符集編碼方式”。你可以通過控制面板裏面的區域選項設置它
foreach (string item in contents)
{
Console.WriteLine(item);
}
txt文件全部讀取:
string str = File.ReadAllText("抽象類特點.txt", Encoding.Default);//相對路徑,本運行程序目錄下(也可絕對路徑)
txt文件以行的形式寫入:(覆蓋原數據)
File.WriteAllLines(@"C:\Users\SpringRain\Desktop\new.txt", new string[] { "aoe", "ewu" });
txt文件寫入:(覆蓋原數據)
File.WriteAllLines(@"C:\Users\SpringRain\Desktop\new.txt", new string[] { "aoe", "ewu" });
txt文件追加寫入:
File.AppendAllText(@"C:\Users\SpringRain\Desktop\new.txt", "看我有木有把你覆蓋掉");