開源php
程序設計html
經常使用組件java
加載圖片,播放音樂、視頻,攝像頭拍照web
文件讀寫(txt、xml、自定義文件格式(後綴名))算法
串口通訊shell
穩定的串口讀寫:http://blog.csdn.net/kolvin2008/article/details/52833480數據庫
窗口通訊類SerialPort:https://www.cnblogs.com/BookCode/p/5583853.html編程
用C#一步步寫串口通訊:http://blog.csdn.net/kasama1953/article/details/51434295json
在win10環境下開發uwp程序,在調用bluetooth的API的時候出現問題c#
原帖地址:https://bbs.csdn.net/topics/392034336?locationNum=13&fps=1
藍牙開發
原文地址:http://blog.csdn.net/yssjz960427031/article/details/50990372
如題,若是你也想用C#在windows上操控電腦自帶藍牙,可是,不知從何下手,那就該看看這篇文章——這篇文章將帶領你入道。也正是這樣,這篇文章的主要內容是介紹操控藍牙所需的支持庫,以及從哪裏下載最新版的支持庫,並教你如何自學與藍牙開發相關的更多知識等。本文涵蓋了經典藍牙(藍牙2.0版本)和低功耗藍牙(即BLE,藍牙4.0版本)。
有過必定編程經驗的人都知道,要想操控某個平臺上的一個硬件,第一件事就是搞清楚這個系統平臺提供了哪些與該硬件相關的API給開發者用,或者,操控該硬件的第三方支持庫有哪些。找到這些是第一步,也是最關鍵的一步。就像治病,首先要找到能治這個病的藥,而後找到藥的說明書,照着說明書「按時按量吃藥治病」——作了個比較形象的比喻。之於開發人員,在找到支持庫後,就該去找支持庫做者提供的使用指南,而後按照使用指南學習使用這個支持庫。那麼,針對「不知道如何操控Windows上的藍牙」這個病該用哪味藥呢?——藥就是這篇文章啦。如今就來按照說明書吃藥啦。
下面分別介紹經典藍牙和BLE相關的支持庫。
稍微用諸如「C# 藍牙」這樣的關鍵詞百度、Google下,就會發現InTheHand.Net.Personal.dll這個支持庫,對!操控經典藍牙就用這個。
InTheHand.Net.Personal.dll這個支持庫是In The Hand公司下32FEET.NET這個項目的成果。該公司由Peter Foot創辦,註冊在英國。下文貼一張摘自官網的照片——看!就是這麼帥,這纔是男神級別的人物!
可經過以下連接瞭解更多的信息:
當給出瞭如上三個連接後,尤爲是第三個,這部分的重點內容基本都講完了。由於在「32FEET.NET項目的源碼託管地址」這個頁面中,就能夠下載到最新版本的InTheHand.Net.Personal.dll這個支持庫,也有這個庫的使用指南,以下圖所示:
說了這麼多,這有個重點:生活在天朝,因爲牆的存在,咱們錯過了不少人間的精彩。因此,你懂了……我爲你們下載了最新的(2016.3.20下載) .Net 3.5和 .Net 3.7版本的InTheHand.Net.Personal.dll,你可從以下地址下載,裏面附有簡要的使用說明,使用零門檻:
具體使用可參照官方的指導文檔,也能夠看看相關的博客,下面僅以我寫過的控制筆記本電腦藍牙來開門的代碼演示下,要特別注意我在下邊代碼的註釋中提到的3個注意——我是從這些坑中爬出來的有經驗的人。
using System; using System.IO; using System.Net.Sockets; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; // [注意1]:要添加以下三個命名空間 using InTheHand.Net; using InTheHand.Net.Bluetooth; using InTheHand.Net.Sockets; namespace TestBluetooth { class Program { static void Main(string[] args) { BluetoothRadio bluetoothRadio = BluetoothRadio.PrimaryRadio; if (bluetoothRadio == null) { Console.WriteLine("沒有找到本機藍牙設備!"); } else { Program p = new Program(); p.localAdapterInfo(bluetoothRadio); p.openDoor(); } } /** * 鏈接目標藍牙設備發送開門指令 * **/ private void openDoor() { BluetoothClient cli = new BluetoothClient(); BluetoothAddress addr = null; BluetoothEndPoint ep = null; try { // [注意2]:要注意MAC地址中字節的對應關係,直接來看順序是相反的,例如 // 以下對應的MAC地址爲——12:34:56:78:9a:bc addr = new BluetoothAddress(new byte[] { 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12 }); ep = new BluetoothEndPoint(addr, BluetoothService.SerialPort); cli.Connect(ep); // 鏈接藍牙 if (cli.Connected) { Stream peerStream = cli.GetStream(); peerStream.WriteByte(0xBB); // 發送開門指令 } } catch (SocketException e) { Console.WriteLine(e.Message); } finally { if (cli != null) { // [注意3]:要延遲必定時間(例如1000毫秒) //避免因鏈接後又迅速斷開而致使藍牙進入異常(傻逼)狀態 Thread.Sleep(1000); cli.Close(); } } } /** * * 顯示本地藍牙的信息 * * **/ private void localAdapterInfo(BluetoothRadio bluetoothRadio) { Console.WriteLine("ClassOfDevice: " + bluetoothRadio.ClassOfDevice); Console.WriteLine("HardwareStatus: " + bluetoothRadio.HardwareStatus); Console.WriteLine("HciRevision: " + bluetoothRadio.HciRevision); Console.WriteLine("HciVersion: " + bluetoothRadio.HciVersion); Console.WriteLine("LmpSubversion: " + bluetoothRadio.LmpSubversion); Console.WriteLine("LmpVersion: " + bluetoothRadio.LmpVersion); Console.WriteLine("LocalAddress: " + bluetoothRadio.LocalAddress); Console.WriteLine("Manufacturer: " + bluetoothRadio.Manufacturer); Console.WriteLine("Mode: " + bluetoothRadio.Mode); Console.WriteLine("Name: " + bluetoothRadio.Name); Console.WriteLine("Remote:" + bluetoothRadio.Remote); Console.WriteLine("SoftwareManufacturer: " + bluetoothRadio.SoftwareManufacturer); Console.WriteLine("StackFactory: " + bluetoothRadio.StackFactory); } } }
(PS:如下所述,都是假設你的筆記本上的藍牙是支持BLE特性的)
畢竟智能硬件興起,還玩經典藍牙顯得有點Low。那麼,問題來了,在電腦上可不可使用BLE呢?答案是——能夠!
可是,有條件限制:只能在Windows 八、Windows 8.一、Windows 10上玩。這個消息也不算太壞哈。
Q:爲何Windows 7上不能玩呢?
A:由於Windows 7及其如下的Windows操做系統中的藍牙協議棧不支持BLE特性。這就好比,你分明在你的筆記本上接了一臺帶掃描功能的打印機,可是你只能打印卻用不了掃描功能,由於你裝的驅動不支持掃描功能。電腦面對的是一臺既能夠打印又能夠掃描的的機器,可是就是不知道如何去控制它來進行掃描。同理,若是硬件支持了BLE(即藍牙4.0)特性,可是藍牙協議棧裏缺乏一些支持這些特性的內容,就沒得玩了。
Q:那麼,我能夠裝個強大點的「驅動」麼?
A:不能夠,這個協議棧不一樣於通常的驅動,Windows的源碼是微軟老大哥一手掌控的,沒有源碼,咱們裝不進去!
Q:那麼,真的就沒得完了麼?
A:換系統唄,換成8及其以上的,一切妥妥的!
想知道Windows系統對藍牙的具體支持狀況,請點擊:General Bluetooth Support in Windows
學習GATT協議是進行BLE開發的基礎,BLE的通信方式和經典藍牙的通信方式有很大的區別,要注意思惟轉換,若是仍是從Socket通信的方式來學習BLE的話,可能會遇到麻煩。
我用C#操做筆記本電腦的藍牙來開門也是出於興趣,上文正是記錄了我從當初的無處下爪到最後有成果這個過程當中的經驗所得,記錄並將其分享出來,但願可以給你們一些幫助、鼓勵甚至啓發,若是能經過個人文字讓別人不要走我走過的彎路,哪怕只有一個,也甚是欣慰了。
地址:http://blog.csdn.net/oqzuser12345678923/article/details/51252545
目前.Net平臺最好用的藍牙庫是InTheHand.net,是由32feet.net提供的shared-source項目,提供短距離領域(personal area networking technologie)的通訊功能,支持bluetooth,Infrared(IrDA)紅外等.
//啓動一個監聽線程 Thread listenThread = new Thread(ReceiveData); listenThread.IsBackground = true; listenThread.Start(); //監聽方法 public void ReceiveData() { while (1 == 1) { try { Guid mGUID = Guid.Parse("db764ac8-4b08-7f25-aafe-59d03c27bae3"); bluetoothListener = new BluetoothListener(mGUID); bluetoothListener.Start(); bluetoothClient = bluetoothListener.AcceptBluetoothClient(); isConnected = true; while (isConnected) { if (bluetoothClient != null && bluetoothClient.Connected) { peerStream = bluetoothClient.GetStream(); } else { break; } byte[] buffer = new byte[100]; peerStream.Read(buffer, 0, 100); receive = Encoding.UTF8.GetString(buffer).ToString(); if (receive == temp) { isConnected = false; } Console.WriteLine(receive + "receiveMsg"); } bluetoothListener.Stop(); bluetoothClient = null; } catch (Exception ex) { Console.Write(ex.Message); } } }
兩個while循環是由於個人安卓app無法修改,沒有作斷開處理,因此強行在服務端斷開了。
若是你藍牙鏈接着的,而且和電腦配對上了,那用這個方法是能夠接受消息的。
個人windows主機是沒有輸出設備的,木有顯示器,而藍牙配對有3中方法,其中justwork表示不驗證,直接配對,可是客戶端代碼動不了,inTheHand.net也沒有找到怎麼設置配對模式。
最後找到藍牙配對PING碼確認的事件,直接把事件註冊後,響應經過就好了。
EventHandler<BluetoothWin32AuthenticationEventArgs> handler = new EventHandler<BluetoothWin32AuthenticationEventArgs>(this.handleRequests); BluetoothWin32Authentication authenticator = new BluetoothWin32Authentication(handler); public void handleRequests(Object thing, BluetoothWin32AuthenticationEventArgs args) { args.Confirm = true; }
異步回調
下面是一個異步回調的例子,主要是發出Post請求,等收到Post請求結果後調用回調方法Done顯示收到的結果。
命名空間
using System.Runtime.Remoting.Messaging;
public delegate string PostHandler(string url, string parame); private void SendPost(string url, string fileName) { try { string paramData = string.Empty; if (!string.IsNullOrEmpty(fileName)) { using (StreamReader sr = new StreamReader(fileName, Encoding.Default)) { paramData = sr.ReadToEnd().Trim(); } } PostHandler postHandler = new PostHandler(Post); IAsyncResult result = postHandler.BeginInvoke(url, paramData, new AsyncCallback(Done), postHandler); } catch (Exception ex) { MessageBox.Show("出錯!異常爲:" + ex.Message); } } public void Done(IAsyncResult result) { PostHandler handler = (PostHandler)((AsyncResult)result).AsyncDelegate; string resultStr = handler.EndInvoke(result); if (!string.IsNullOrEmpty(resultStr)) { DisplayResult(resultStr); } else { DisplayResult("未收到結果,請從新發送!"); } MessageBox.Show("收到結果!"); } private void DisplayResult(string result) { if (this.InvokeRequired) { this.Invoke(new MethodInvoker(delegate() { DisplayResult(result); })); } else { textBox_Result.Text = result; } } //public CookieContainer CookieContainer { get; set; } private string Post(string postUrl, string paramData) { string result = string.Empty; Stream stream = null; StreamReader sr = null; HttpWebResponse response = null; try { byte[] byteArray = Encoding.UTF8.GetBytes(paramData); HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(new Uri(postUrl)); webReq.Method = "POST"; webReq.ContentType = "application/json; charset=utf-8"; //webReq.ContentType = "application/x-www-form-urlencoded"; webReq.Accept = "text/json"; //"image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"; webReq.UserAgent = "valwell.com/1.0"; webReq.ContentLength = byteArray.Length; webReq.ServicePoint.Expect100Continue = false; //webReq.CookieContainer = CookieContainer; stream = webReq.GetRequestStream(); stream.Write(byteArray, 0, byteArray.Length); response = (HttpWebResponse)webReq.GetResponse(); if (response.StatusCode == HttpStatusCode.OK) { //response.Cookies = CookieContainer.GetCookies(webReq.RequestUri); sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8); result = sr.ReadToEnd(); } else { Debug.WriteLine(response.StatusCode); } } catch (Exception ex) { string exMessage = ex.Message; } finally { if (sr != null) { sr.Close(); } if (response != null) { response.Close(); } if (stream != null) { stream.Close(); } } return result; } /// <summary> /// 設置是否容許不安全的鏈接 /// </summary> /// <param name="useUnsafe"></param> /// <returns></returns> public static bool SetAllowUnsafeHeaderParsing20(bool useUnsafe) { //Get the assembly that contains the internal class System.Reflection.Assembly aNetAssembly = System.Reflection.Assembly.GetAssembly(typeof(System.Net.Configuration.SettingsSection)); if (aNetAssembly != null) { //Use the assembly in order to get the internal type for the internal class Type aSettingsType = aNetAssembly.GetType("System.Net.Configuration.SettingsSectionInternal"); if (aSettingsType != null) { //Use the internal static property to get an instance of the internal settings class. //If the static instance isn't created allready the property will create it for us. object anInstance = aSettingsType.InvokeMember("Section", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.GetProperty | System.Reflection.BindingFlags.NonPublic, null, null, new object[] { }); if (anInstance != null) { //Locate the private bool field that tells the framework is unsafe header parsing should be allowed or not System.Reflection.FieldInfo aUseUnsafeHeaderParsing = aSettingsType.GetField("useUnsafeHeaderParsing", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); if (aUseUnsafeHeaderParsing != null) { aUseUnsafeHeaderParsing.SetValue(anInstance, useUnsafe); return true; } } } } return false; }
C#使用Log4Net記錄日誌
參考文檔網址:
一、http://www.cnblogs.com/wangsaiming/archive/2013/01/11/2856253.html
二、http://www.cnblogs.com/jys509/p/4569874.html
三、http://zhoufoxcn.blog.51cto.com/792419/429988/
四、http://blog.csdn.net/suixufeng/article/details/50259617
有時間本身再寫一篇專門的文檔
文件讀寫
1、獲取路徑
1.獲取和設置當前目錄的徹底限定路徑。 string str = System.Environment.CurrentDirectory;
Result: C:\xxx\xxx
2.獲取啓動了應用程序的可執行文件的路徑,不包括可執行文件的名稱。 string str = System.Windows.Forms.Application.StartupPath; Result: C:\xxx\xxx
3.獲取新的 Process 組件並將其與當前活動的進程關聯的主模塊的完整路徑,包含文件名。 string str = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; Result: C:\xxx\xxx\xxx.exe
4.獲取當前 Thread 的當前應用程序域的基目錄,它由程序集衝突解決程序用來探測程序集。 string str = System.AppDomain.CurrentDomain.BaseDirectory; Result: C:\xxx\xxx\
5.獲取應用程序的當前工做目錄。 string str = System.IO.Directory.GetCurrentDirectory();
Result: C:\xxx\xxx
6.獲取和設置包含該應用程序的目錄的名稱。 string str = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase; Result: C:\xxx\xxx\
7.獲取當前進程的完整路徑,包含文件名。 string str = this.GetType().Assembly.Location;
Result: C:\xxx\xxx\xxx.exe
8.獲取啓動了應用程序的可執行文件的路徑,包括可執行文件的名稱。 string str = System.Windows.Forms.Application.ExecutablePath; Result: C:\xxx\xxx\xxx.exe
2、目錄與文件(Directory類和File類)
下面是一個例子,原文地址http://www.cnblogs.com/szytwo/archive/2012/03/22/2411703.html
protected void Button1_Click(object sender, EventArgs e)
{
if (Directory.Exists(Server.MapPath("~/upimg/hufu")) == false)//若是不存在就建立file文件夾
{
Directory.CreateDirectory(Server.MapPath("~/upimg/hufu"));
}
//Directory.Delete(Server.MapPath("~/upimg/hufu"), true);//刪除文件夾以及文件夾中的子目錄,文件
//判斷文件的存在
if (File.Exists(Server.MapPath("~/upimg/Data.html")))
{
Response.Write("Yes");
//存在文件
}
else
{
Response.Write("No");
//不存在文件
File.Create(MapPath("~/upimg/Data.html"));//建立該文件
}
string name = GetFiles.FileName;//獲取已上傳文件的名字
string size = GetFiles.PostedFile.ContentLength.ToString();//獲取已上傳文件的大小
string type = GetFiles.PostedFile.ContentType;//獲取已上傳文件的MIME
string postfix = name.Substring(name.LastIndexOf(".") + 1);//獲取已上傳文件的後綴
string ipath = Server.MapPath("upimg") +"\\"+ name;//獲取文件的實際路徑
string fpath = Server.MapPath("upfile") + "\\" + name;
string dpath = "upimg\\" + name;//判斷寫入數據庫的虛擬路徑
ShowPic.Visible = true;//激活
ShowText.Visible = true;//激活
//判斷文件格式
if (name == "") {
Response.Write("<script>alert('上傳文件不能爲空')</script>");
}
else{
if (postfix == "jpg" || postfix == "gif" || postfix == "bmp" || postfix == "png")
{
GetFiles.SaveAs(ipath);
ShowPic.ImageUrl = dpath;
ShowText.Text = "你上傳的圖片名稱是:" + name + "<br>" + "文件大小:" + size + "KB" + "<br>" + "文件類型:" + type + "<br>" + "存放的實際路徑爲:" + ipath;
}
else
{
ShowPic.Visible = false;//隱藏圖片
GetFiles.SaveAs(fpath);//因爲不是圖片文件,所以轉存在upfile這個文件夾
ShowText.Text = "你上傳的文件名稱是:" + name + "<br>" + "文件大小:" + size + "KB" + "<br>" + "文件類型:" + type + "<br>" + "存放的實際路徑爲:" + fpath;
}
3、文件的讀寫
C#對文本文件的幾張讀寫方法總結,原文地址http://www.cr173.com/html/18141_1.html
計算機在最初只支持ASCII編碼,可是後來爲了支持其餘語言中的字符(好比漢字)以及一些特殊字符(好比€),就引入了Unicode字符集。基於Unicode字符集的編碼方式有不少,好比UTF-七、UTF-八、Unicode以及UTF-32。在Windows操做系統中,一個文本文件的前幾個字節是用來指定該文件的編碼方式的。
若是你使用NotePad或WordPad來打開一個文本文件,你並不用擔憂該文件的編碼方式,由於這些應用程序會先讀取文件的前幾個字節來肯定該文件的編碼方式,而後用正確的編碼將文本中的每一個字符顯示出來。下面的圖中,能夠看到當用NotePad記事本保存一個文檔時,能夠選擇的編碼(Encoding)方式有哪些。
用.Net讀取文本文件或寫入文本文件,你都不需要擔憂編碼方式。.Net已經將這些封裝好了。在讀取一個文本文件的時候,若是你已經知道文本使用的是什麼編碼方式,你能夠指定使用哪一種編碼方式讀取文本,不然若是不指定編碼方式,.Net會讀取文本的前幾個字節來肯定使用哪一種編碼方式讀取文件內容的。在寫入文本文件的時候,你也能夠指定你想使用的編碼方式。若是你沒有指定編碼,.Net會根據寫入的文本是否含有特殊字符來決定編碼方式。若是沒有特殊字符,就採用ASCII編碼,若是有特殊字符,就採用UTF-8編碼。
(一) 讀取文件
若是你要讀取的文件內容不是不少,可使用 File.ReadAllText(FilePath) 或指定編碼方式 File.ReadAllText(FilePath, Encoding)的方法。
它們都一次將文本內容所有讀完,並返回一個包含所有文本內容的字符串
string str = File.ReadAllText(@"c:\temp\ascii.txt");
// 也能夠指定編碼方式
string str2 = File.ReadAllText(@"c:\temp\ascii.txt", Encoding.ASCII);
也可使用方法File.ReadAllLines。該方法返回一個字符串數組。每一行都是一個數組元素。
string[] strs = File.ReadAllLines(@"c:\temp\ascii.txt");
// 也能夠指定編碼方式
string[] strs2 = File.ReadAllLines(@"c:\temp\ascii.txt", Encoding.ASCII);
當文本的內容比較大時,咱們就不要將文本內容一次讀完,而應該採用流(Stream)的方式來讀取內容。.Net爲咱們封裝了StreamReader類。初始化StreamReader類有不少種方式。下面我羅列出幾種
StreamReader sr1 = new StreamReader(@"c:\temp\utf-8.txt");
// 一樣也能夠指定編碼方式
StreamReader sr2 = new StreamReader(@"c:\temp\utf-8.txt", Encoding.UTF8);
FileStream fs = new FileStream(@"C:\temp\utf-8.txt", FileMode.Open, FileAccess.Read, FileShare.None);
StreamReader sr3 = new StreamReader(fs);
StreamReader sr4 = new StreamReader(fs, Encoding.UTF8);
FileInfo myFile = new FileInfo(@"C:\temp\utf-8.txt");
// OpenText 建立一個UTF-8 編碼的StreamReader對象
StreamReader sr5 = myFile.OpenText();
// OpenText 建立一個UTF-8 編碼的StreamReader對象
StreamReader sr6 = File.OpenText(@"C:\temp\utf-8.txt");
初始化完成以後,你能夠每次讀一行,也能夠每次讀一個字符 ,還能夠每次讀幾個字符,甚至也能夠一次將全部內容讀完。
// 讀一行
string nextLine = sr.ReadLine();
// 讀一個字符
int nextChar = sr.Read();
// 讀100個字符
int nChars = 100;
char[] charArray = new char[nChars];
int nCharsRead = sr.Read(charArray, 0, nChars);
// 所有讀完
string restOfStream = sr.ReadToEnd();
使用完StreamReader以後,不要忘記關閉它: sr.Closee();
假如咱們須要一行一行的讀,將整個文本文件讀完,下面看一個完整的例子:
StreamReader sr = File.OpenText(@"C:\temp\ascii.txt");
string nextLine;
while ((nextLine = sr.ReadLine()) != null)
{
Console.WriteLine(nextLine);
}
sr.Close();
(二) 寫入文件
寫文件和讀文件同樣,若是你要寫入的內容不是不少,可使用File.WriteAllText方法來一次將內容所有寫如文件。若是你要將一個字符串的內容寫入文件,能夠用File.WriteAllText(FilePath) 或指定編碼方式 File.WriteAllText(FilePath, Encoding)方法。
string str1 = "Good Morning!"; File.WriteAllText(@"c:\temp\test\ascii.txt", str1); // 也能夠指定編碼方式 File.WriteAllText(@"c:\temp\test\ascii-2.txt", str1, Encoding.ASCII);
若是你有一個字符串數組,你要將每一個字符串元素都寫入文件中,能夠用File.WriteAllLines方法:
string[] strs = { "Good Morning!", "Good Afternoon!" }; File.WriteAllLines(@"c:\temp\ascii.txt", strs); File.WriteAllLines(@"c:\temp\ascii-2.txt", strs, Encoding.ASCII);
使用File.WriteAllText或File.WriteAllLines方法時,若是指定的文件路徑不存在,會建立一個新文件;若是文件已經存在,則會覆蓋原文件。
當要寫入的內容比較多時,一樣也要使用流(Stream)的方式寫入。.Net封裝的類是StreamWriter。初始化StreamWriter類一樣有不少方式:
// 若是文件不存在,建立文件; 若是存在,覆蓋文件
StreamWriter sw1 = new StreamWriter(@"c:\temp\utf-8.txt");
// 也能夠指定編碼方式
// true 是 append text, false 爲覆蓋原文件
StreamWriter sw2 = new StreamWriter(@"c:\temp\utf-8.txt", true, Encoding.UTF8);
// FileMode.CreateNew: 若是文件不存在,建立文件;若是文件已經存在,拋出異常
FileStream fs = new FileStream(@"C:\temp\utf-8.txt", FileMode.CreateNew, FileAccess.Write, FileShare.Read);
// UTF-8 爲默認編碼
StreamWriter sw3 = new StreamWriter(fs);
StreamWriter sw4 = new StreamWriter(fs, Encoding.UTF8);
// 若是文件不存在,建立文件; 若是存在,覆蓋文件
FileInfo myFile = new FileInfo(@"C:\temp\utf-8.txt");
StreamWriter sw5 = myFile.CreateText();
初始化完成後,能夠用StreamWriter對象一次寫入一行,一個字符,一個字符數組,甚至一個字符數組的一部分。
// 寫一個字符
sw.Write('a');
// 寫一個字符數組
char[] charArray = new char[100];
// initialize these characters
sw.Write(charArray);
// 寫一個字符數組的一部分
sw.Write(charArray, 10, 15);
一樣,StreamWriter對象使用完後,不要忘記關閉。sw.Close(); 最後來看一個完整的使用StreamWriter一次寫入一行的例子:
FileInfo myFile = new FileInfo(@"C:\temp\utf-8.txt");
StreamWriter sw = myFile.CreateText();
string[] strs = { "早上好", "下午好" };
foreach (var s in strs)
{
sw.WriteLine(s);
}
sw.Close();
寫入文本文件例子
class WriteTextFile
{
static void Main()
{
//若是文件不存在,則建立;存在則覆蓋
//該方法寫入字符數組換行顯示
string[] lines = { "first line", "second line", "third line","第四行" };
System.IO.File.WriteAllLines(@"C:\testDir\test.txt", lines, Encoding.UTF8);
//若是文件不存在,則建立;存在則覆蓋
string strTest = "該例子測試一個字符串寫入文本文件。";
System.IO.File.WriteAllText(@"C:\testDir\test1.txt", strTest, Encoding.UTF8);
//在將文本寫入文件前,處理文本行
//StreamWriter一個參數默認覆蓋
//StreamWriter第二個參數爲false覆蓋現有文件,爲true則把文本追加到文件末尾
using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\testDir\test2.txt",true))
{
foreach (string line in lines)
{
if (!line.Contains("second"))
{
file.Write(line);//直接追加文件末尾,不換行
file.WriteLine(line);// 直接追加文件末尾,換行
}
}
}
}
}
讀取文本文件例子
class ReadTextFile
{
static void Main()
{
//直接讀取出字符串
string text = System.IO.File.ReadAllText(@"C:\testDir\test1.txt");
Console.WriteLine(text);
//按行讀取爲字符串數組
string[] lines = System.IO.File.ReadAllLines(@"C:\testDir\test.txt");
foreach (string line in lines)
{
Console.WriteLine(line);
}
//從頭至尾以流的方式讀出文本文件
//該方法會一行一行讀出文本
using (System.IO.StreamReader sr = new System.IO.StreamReader(@"C:\testDir\test.txt"))
{
string str;
while ((str = sr.ReadLine()) != null)
{
Console.WriteLine(str);
}
}
Console.Read();
}
}
4、註冊自定義文件類型
原文地址:http://blog.csdn.net/jiutao_tang/article/details/6563646
事實上有三種方式能夠實現文件類型的註冊,筆者在網上看到的都是手動實現的或程序實現的,其實也能夠直接在工程屬性裏進行設置。
1. 工程屬性定義
項目--->工程屬性--->發佈--->選項--->文件關聯--->設置擴展名、說明、ProgID(自定義)、圖標便可。
2. 手工實現文件類型關聯
每個文件類型的信息被保存在註冊表中的 'HKEY_CLASSES_ROOT'下面。假設咱們自定義的文件類型的後綴爲.hyp,文件名爲Test_File_Hype (中間不能有空格).
首先在HKEY_CLASSES_ROOT下建立 .hyp
HKEY_CLASSES_ROOT/.hyp
將[默認]鍵值改成"Test_File_Hype"。而後在HKEY_CLASSES_ROOT下添加主鍵 Test_File_Hype
HKEY_CLASSES_ROOT/Test_File_Hype
按照下面的路徑添加新的主鍵
HKEY_CLASSES_ROOT/Test_File_Hype/Shell
HKEY_CLASSES_ROOT/Test_File_Hype/Shell/Open
HKEY_CLASSES_ROOT/Test_File_Hype/Shell/Open/Command
將下面的字符做爲Command的鍵值
your application path.exe %1
(例如 C:/WINDOWS/HYP/HYP.EXE %1)
或許你還想爲本身的文件類型加上同本身的執行文件同樣的圖標,很簡單,照下面的方法添加就好了。
HKEY_CLASSES_ROOT/Test_File_Hype/DefaultIcon
輸入鍵值:
your application path.EXE,0
後面的零表示文件的圖標同程序的主圖標一致,若是你的程序有不少圖標,換一換數字就可改變文件顯
參考:http://www.codesky.net/article/doc/200308/2003082482622669.htm
3. C#編程實現自定義文件類型關聯應用程序
在咱們本身編寫的應用中,常常會用自定義類型的文件的來保存與應用相關的數據,好比.xcf文件就是XCodeFactory應用程序的項目文件。若是沒 有向Windows註冊表註冊該文件類型,那麼.xcf文件的圖標將是windows的文件默認圖標,而且你雙擊一個a.xcf文件,也不會自動啓動 XCodeFactory應用程序來加載a.xcf文件。如何使.xcf文件的圖標變成我本身喜好的圖標、如何完成像點擊.doc文件就自動打開word 程序的功能,下面將告訴你解決方案。
咱們能夠經過手動修改註冊表來完成上述任務,更好的方式是,經過程序來實現。這樣,在安裝應用程序時,就能夠自動的註冊自定義文件類型 了。我經過FileTypeRegister靜態類來完成這些功能。首先,將註冊須要用到的信息封裝成FileTypeRegInfo,定義以下:
public class FileTypeRegInfo
{
/// <summary>
/// 目標類型文件的擴展名
/// </summary>
public string ExtendName; //".xcf"
/// <summary>
/// 目標文件類型說明
/// </summary>
public string Description; //"XCodeFactory項目文件"
/// <summary>
/// 目標類型文件關聯的圖標
/// </summary>
public string IcoPath;
/// <summary>
/// 打開目標類型文件的應用程序
/// </summary>
public string ExePath;
public FileTypeRegInfo()
{
}
public FileTypeRegInfo(string extendName)
{
this.ExtendName = extendName;
}
}
FileTypeRegister類主要是操做註冊表中的內容,實現以下:
/// <summary>
/// FileTypeRegister 用於註冊自定義的文件類型。
/// zhuweisky 2005.08.31
/// </summary>
public class FileTypeRegister
{
#region RegisterFileType
/// <summary>
/// RegisterFileType 使文件類型與對應的圖標及應用程序關聯起來。
/// </summary>
public static void RegisterFileType(FileTypeRegInfo regInfo)
{
if (FileTypeRegistered(regInfo.ExtendName))
{
return;
}
string relationName = regInfo.ExtendName.Substring(1, regInfo.ExtendName.Length - 1).ToUpper() + "_FileType";
RegistryKey fileTypeKey = Registry.ClassesRoot.CreateSubKey(regInfo.ExtendName);
fileTypeKey.SetValue("", relationName);
fileTypeKey.Close();
RegistryKey relationKey = Registry.ClassesRoot.CreateSubKey(relationName);
relationKey.SetValue("", regInfo.Description);
RegistryKey iconKey = relationKey.CreateSubKey("DefaultIcon");
iconKey.SetValue("", regInfo.IcoPath);
RegistryKey shellKey = relationKey.CreateSubKey("Shell");
RegistryKey openKey = shellKey.CreateSubKey("Open");
RegistryKey commandKey = openKey.CreateSubKey("Command");
commandKey.SetValue("", regInfo.ExePath + " %1");
relationKey.Close();
}
/// <summary>
/// GetFileTypeRegInfo 獲得指定文件類型關聯信息
/// </summary>
public static FileTypeRegInfo GetFileTypeRegInfo(string extendName)
{
if (!FileTypeRegistered(extendName))
{
return null;
}
FileTypeRegInfo regInfo = new FileTypeRegInfo(extendName);
string relationName = extendName.Substring(1, extendName.Length - 1).ToUpper() + "_FileType";
RegistryKey relationKey = Registry.ClassesRoot.OpenSubKey(relationName);
regInfo.Description = relationKey.GetValue("").ToString();
RegistryKey iconKey = relationKey.OpenSubKey("DefaultIcon");
regInfo.IcoPath = iconKey.GetValue("").ToString();
RegistryKey shellKey = relationKey.OpenSubKey("Shell");
RegistryKey openKey = shellKey.OpenSubKey("Open");
RegistryKey commandKey = openKey.OpenSubKey("Command");
string temp = commandKey.GetValue("").ToString();
regInfo.ExePath = temp.Substring(0, temp.Length - 3);
return regInfo;
}
/// <summary>
/// UpdateFileTypeRegInfo 更新指定文件類型關聯信息
/// </summary>
public static bool UpdateFileTypeRegInfo(FileTypeRegInfo regInfo)
{
if (!FileTypeRegistered(regInfo.ExtendName))
{
return false;
}
string extendName = regInfo.ExtendName;
string relationName = extendName.Substring(1, extendName.Length - 1).ToUpper() + "_FileType";
RegistryKey relationKey = Registry.ClassesRoot.OpenSubKey(relationName, true);
relationKey.SetValue("", regInfo.Description);
RegistryKey iconKey = relationKey.OpenSubKey("DefaultIcon", true);
iconKey.SetValue("", regInfo.IcoPath);
RegistryKey shellKey = relationKey.OpenSubKey("Shell");
RegistryKey openKey = shellKey.OpenSubKey("Open");
RegistryKey commandKey = openKey.OpenSubKey("Command", true);
commandKey.SetValue("", regInfo.ExePath + " %1");
relationKey.Close();
return true;
}
/// <summary>
/// FileTypeRegistered 指定文件類型是否已經註冊
/// </summary>
public static bool FileTypeRegistered(string extendName)
{
RegistryKey softwareKey = Registry.ClassesRoot.OpenSubKey(extendName);
if (softwareKey != null)
{
return true;
}
return false;
}
#endregion
}
要注意的是commandKey.SetValue("" ,regInfo.ExePath + " %1") ;其中" %1"表示將被雙擊的文件的路徑傳給目標應用程序,這樣在雙擊a.xcf文件時,XCodeFactory才知道要打開哪一個文件,因此應用程序的Main方法要被改寫爲帶有參數的形式,就像下面的樣子:
[STAThread]
static void Main(string[] args)
{
if ((args != null) && (args.Length > 0))
{
string filePath = "";
for (int i = 0; i < args.Length; i++)
{
filePath += " " + args[i];
}
MainForm.XcfFilePath = filePath.Trim();
}
Application.Run(new MainForm());
}
關於自定義文件類型的註冊,本文實現的是最基本的功能,若是須要更多的高級功能,也能夠類推實現之。
注:
(1)應用程序的Main方法在Program.cs文件中,能夠把原來無參的main方法註釋掉;
(2)MainForm就是應用程序的啓動窗體,能夠改成本身的
(3)filePath.Trim() 就是獲取的文件路徑了
(4)using Microsoft.Win32; //RegistryKey 位於 Microsoft.Win32 命名空間
(5)註冊文件類型後,文件圖標可能並不會當即生效(需註銷登陸或重啓Explorer進程)。咱們能夠採起重啓Explorer進程的方式使之當即生效,可參考示例程序中的代碼。
個人一個實例:在Form_load事件中進行註冊:
private void Form1_Load(object sender, EventArgs e)
{
action = true;
if (!FileTypeRegister.FileTypeRegistered(".hd")) //若是文件類型沒有註冊,則進行註冊
{
FileTypeRegInfo fileTypeRegInfo = new FileTypeRegInfo(".hd"); //文件類型信息
fileTypeRegInfo.Description = "巷道支護系統工程文件";
fileTypeRegInfo.ExePath = Application.ExecutablePath;
fileTypeRegInfo.ExtendName = ".hd";
fileTypeRegInfo.IcoPath = Application.ExecutablePath; //文件圖標使用應用程序的
FileTypeRegister fileTypeRegister = new FileTypeRegister(); //註冊
FileTypeRegister.RegisterFileType(fileTypeRegInfo);
Process[] process = Process.GetProcesses(); //重啓Explorer進程,使更新當即生效
var p = (from proc in process
where proc.ProcessName.Equals("explorer")
select proc).FirstOrDefault();
p.Kill();
}
}
1、Random 生成不重複隨機數
轉自:http://www.cnblogs.com/huangfr/archive/2012/03/27/2420464.html
命名空間:System
表示僞隨機數生成器,一種可以產生知足某些隨機性統計要求的數字序列的設備。
僞隨機數是以相同的機率從一組有限的數字中選取的。所選數字並不具備徹底的隨機性,由於它們是用一種肯定的數學算法選擇的,可是從實用的角度而言,其隨機程度已足夠了。
僞隨機數的生成是從種子值開始。若是反覆使用同一個種子,就會生成相同的數字系列。產生不一樣序列的一種方法是使種子值與時間相關,從而對於 Random 的每一個新實例,都會產生不一樣的系列。默認狀況下,Random 類的無參數構造函數使用系統時鐘生成其種子值,而參數化構造函數可根據當前時間的計時週期數採用 Int32 值。可是,由於時鐘的分辨率有限,因此,若是使用無參數構造函數連續建立不一樣的 Random 對象,就會建立生成相同隨機數序列的隨機數生成器。
經過建立單個而不是多個 Random 對象能夠避免此問題。
若要提升性能,請建立一個隨時間推移能生成多個隨機數的 Random 對象,而不要反覆新建會生成同一個隨機數的 Random 對象。
名稱 ● 說明
Equals ● 肯定指定的 Object 是否等於當前的 Object。(繼承自 Object。)
Finalize ● 容許 Object 在「垃圾回收」回收 Object 以前嘗試釋放資源並執行其餘清理操做。(繼承自 Object。)
GetHashCode ● 用做特定類型的哈希函數。(繼承自 Object。)
GetType ● 獲取當前實例的 Type。(繼承自 Object。)
MemberwiseClone ● 建立當前 Object 的淺表副本。(繼承自 Object。)
Next ● 已重載。 返回隨機數。
NextBytes ● 用隨機數填充指定字節數組的元素。
NextDouble ● 返回一個介於 0.0 和 1.0 之間的隨機數。
Sample ● 返回一個介於 0.0 和 1.0 之間的隨機數。
ToString ● 返回表示當前 Object 的 String。(繼承自 Object。)
咱們可使用兩種方式初始化一個隨機數發生器:
第一種方法不指定隨機種子,系統自動選取當前時間做爲隨機種子:
Random ro = new Random();
第二種方法能夠指定一個int型參數做爲隨機種子:
int iSeed=10;
Random ro = new Random(10);
long tick = DateTime.Now.Ticks;
Random ran = new Random((int)(tick & 0xffffffffL) | (int) (tick >> 32));
這樣能夠保證99%不是同樣。
以後,咱們就可使用這個Random類的對象來產生隨機數,這時候要用到Random.Next()方法。這個方法使用至關靈活,你甚至能夠指定產生的隨機數的上下限。
不指定上下限的使用以下:
int iResult;
iResult=ro.Next();
下面的代碼指定返回小於100的隨機數:
int iResult;
int iUp=100;
iResult=ro.Next(iUp);
而下面這段代碼則指定返回值必須在50-100的範圍以內:
int iResult;
int iUp=100;
int iDown=50;
iResult=ro.Next(iDown,iUp);
除了Random.Next()方法以外,Random類還提供了Random.NextDouble()方法產生一個範圍在0.0-1.0之間的隨機的雙精度浮點數:
double dResult;
dResult=ro.NextDouble();
可是用Random類生成題號,會出現重複,特別是在數量較小的題目中要生成不重複的的題目是很難的。
參考了網上的一些方法,找到兩類解決方法,一類是經過隨機種子入手,使每一次的隨機種子不一樣,來保證不重複;第二類是使用一些數據結構和算法。
下面主要就第二類介紹幾個方法:
方法1:思想是用一個數組來保存索引號,先隨機生成一個數組位置,而後把隨機抽取到的位置的索引號取出來,並把最後一個索引號複製到當前的數組位置,而後使隨機數的上限減一,具體如:先把這100個數放在一個數組內,每次隨機取一個位置(第一次是1-100,第二次是1-99,...),將該位置的數用最後的數代替。
int[] index = new int[15]; for (int i = 0; i < 15; i++) index = i; Random r = new Random(); //用來保存隨機生成的不重複的10個數 int[] result = new int[10]; int site = 15;//設置上限 int id; for (int j = 0; j < 10; j++) { id = r.Next(1, site - 1); //在隨機位置取出一個數,保存到結果數組 result[j] = index[id]; //最後一個數複製到當前位置 index[id] = index[site - 1]; //位置的上限減小一 site--; } |
方法2:利用Hashtable。
Hashtable hashtable = new Hashtable(); Random rm = new Random(); int RmNum = 10; for (int i = 0; hashtable.Count < RmNum; i++) { int nValue = rm.Next(100); if (!hashtable.ContainsValue(nValue) && nValue != 0) { hashtable.Add(nValue, nValue); Console.WriteLine(nValue.ToString()); } } |
方法3:遞歸,用它來檢測生成的隨機數是否有重複,若是取出來的數字和已取得的數字有重複就從新隨機獲取。
Random ra=new Random(unchecked((int)DateTime.Now.Ticks)); int[] arrNum=new int[10]; int tmp=0; int minValue=1; int maxValue=10; for (int i=0;i<10;i++) { tmp=ra.Next(minValue,maxValue); //隨機取數 arrNum=getNum(arrNum,tmp,minValue,maxValue,ra); //取出值賦到數組中 } ......... ......... public int getNum(int[] arrNum,int tmp,int minValue,int maxValue,Random ra) { int n=0; while (n<=arrNum.Length-1) { if (arrNum[n]==tmp) //利用循環判斷是否有重複 { tmp=ra.Next(minValue,maxValue); //從新隨機獲取。 getNum(arrNum,tmp,minValue,maxValue,ra);//遞歸:若是取出來的數字和已取得的數字有重複就從新隨機獲取。 } n++; } return tmp; } |
來源:我和將來有約會
2008-06-17 01:21 by nasa
using System;
using System.Security.Cryptography;
public class RNG
{
private static RNGCryptoServiceProvider rngp = new RNGCryptoServiceProvider();
private static byte[] rb = new byte[4];
/// <summary>
/// 產生一個非負數的亂數
/// </summary>
public static int Next()
{
rngp.GetBytes(rb);
int value = BitConverter.ToInt32(rb, 0);
if (value < 0) value = -value;
return value;
}
/// <summary>
/// 產生一個非負數且最大值在 max 如下的亂數
/// </summary>
/// <param name="max">最大值</param>
public static int Next(int max)
{
rngp.GetBytes(rb);
int value = BitConverter.ToInt32(rb, 0);
value = value % (max + 1);
if (value < 0) value = -value;
return value;
}
/// <summary>
/// 產生一個非負數且最小值在 min 以上最大值在 max 如下的亂數
/// </summary>
/// <param name="min">最小值</param>
/// <param name="max">最大值</param>
public static int Next(int min, int max)
{
int value = Next(max - min) + min;
return value;
}
}
2、線程安全的單例模式
原文地址:http://www.oschina.net/code/snippet_111708_25417
線程安全的單例模式實現有幾種思路,我的認爲第2種方案最優雅:
一、餓漢式
二、藉助內部類
三、普通加鎖解決
四、雙重檢測,但要注意寫法
若是單體模式繼續擴展爲N元單體模式,那就是對象池模式了
public
class
Singleton {
private
final
static
Singleton INSTANCE =
new
Singleton();
private
Singleton() { }
public
static
Singleton getInstance() {
return
INSTANCE;
}
}
public
class
Singleton {
private
Singleton() { }
private
static
class
SingletonHolder {
private
final
static
Singleton INSTANCE =
new
Singleton();
}
public
static
Singleton getInstance() {
return
SingletonHolder.INSTANCE;
}
}
屬於懶漢式單例,由於Java機制規定,內部類SingletonHolder只有在getInstance()方法第一次調用的時候纔會被加載(實現了lazy),並且其加載過程是線程安全的。內部類加載的時候實例化一次instance。
public
class
Singleton {
private
static
Singleton instance =
null
;
private
Singleton() { }
public
static
synchronized
Singleton getInstance() {
if
(instance ==
null
) {
instance =
new
Singleton();
}
return
instance;
}
}
雖然解決了線程安全問題,可是每一個線程調用getInstance都要加鎖,咱們想要只在第一次調用getInstance時加鎖,請看下面的雙重檢測方案
public
class
Singleton {
private
static
Singleton instance =
null
;
private
Singleton() { }
public
static
Singleton getInstance() {
if
(instance ==
null
) {
synchronzied(Singleton.
class
) {
Singleton temp = instance;
if
(temp ==
null
) {
temp =
new
Singleton();
instance = temp
}
}
}
return
instance;
}
}
因爲指令重排序問題,因此不能夠直接寫成下面這樣:
public
class
Singleton {
private
static
Singleton instance =
null
;
private
Singleton() { }
public
static
Singleton getInstance() {
if
(instance ==
null
) {
synchronzied(Singleton.
class
) {
if
(instance ==
null
) {
instance =
new
Singleton();
}
}
}
return
instance;
}
}
可是若是instance實例變量用
volatile
修飾就能夠了,
volatile
修飾的話就能夠確保instance =
new
Singleton();對應的指令不會重排序,以下的單例代碼也是線程安全的:
public
class
Singleton {
private
static
volatile
Singleton instance =
null
;
private
Singleton() { }
public
static
Singleton getInstance() {
if
(instance ==
null
) {
synchronzied(Singleton.
class
) {
if
(instance ==
null
) {
instance =
new
Singleton();
}
}
}
return
instance;
}
}
如下轉自:http://www.cnblogs.com/akwwl/p/3240813.html
1.添加命名空間
System.IO;
System.Text;
2.文件的讀取
(1).使用FileStream類進行文件的讀取,並將它轉換成char數組,而後輸出。
byte[] byData = new byte[100]; char[] charData = new char[1000]; public void Read() { try { FileStream file = new FileStream("E:\\test.txt", FileMode.Open); file.Seek(0, SeekOrigin.Begin); file.Read(byData, 0, 100); //byData傳進來的字節數組,用以接受FileStream對象中的數據,第2個參數是字節數組中開始寫入數據的位置,它一般是0,表示從數組的開端文件中向數組寫數據,最後一個參數規定從文件讀多少字符. Decoder d = Encoding.Default.GetDecoder(); d.GetChars(byData, 0, byData.Length, charData, 0); Console.WriteLine(charData); file.Close(); } catch (IOException e) { Console.WriteLine(e.ToString()); } }
(2).使用StreamReader讀取文件,而後一行一行的輸出。
public void Read(string path) { StreamReader sr = new StreamReader(path,Encoding.Default); String line; while ((line = sr.ReadLine()) != null) { Console.WriteLine(line.ToString()); } }
3.文件的寫入
(1).使用FileStream類建立文件,而後將數據寫入到文件裏。
public void Write() { FileStream fs = new FileStream("E:\\ak.txt", FileMode.Create); //得到字節數組 byte[] data = System.Text.Encoding.Default.GetBytes("Hello World!"); //開始寫入 fs.Write(data, 0, data.Length); //清空緩衝區、關閉流 fs.Flush(); fs.Close(); }
(2).使用FileStream類建立文件,使用StreamWriter類,將數據寫入到文件。
public void Write(string path) { FileStream fs = new FileStream(path, FileMode.Create); StreamWriter sw = new StreamWriter(fs); //開始寫入 sw.Write("Hello World!!!!"); //清空緩衝區 sw.Flush(); //關閉流 sw.Close(); fs.Close(); }
以上就完成了,txt文本文檔的數據讀取與寫入。
①
1 private void GetIP() 2 { 3 string hostName = Dns.GetHostName();//本機名 4 //System.Net.IPAddress[] addressList = Dns.GetHostByName(hostName).AddressList;//會警告GetHostByName()已過時,我運行時且只返回了一個IPv4的地址 5 System.Net.IPAddress[] addressList = Dns.GetHostAddresses(hostName);//會返回全部地址,包括IPv4和IPv6 6 foreach (IPAddress ip in addressList) 7 { 8 listBox1.Items.Add(ip.ToString()); 9 } 10 }
②使用IPHostEntry獲取本機局域網地址
1 static string GetLocalIp() 2 { 3 string hostname = Dns.GetHostName();//獲得本機名 4 //IPHostEntry localhost = Dns.GetHostByName(hostname);//方法已過時,只獲得IPv4的地址 5 <SPAN style="WHITE-SPACE: pre"> </SPAN> IPHostEntry localhost = Dns.GetHostEntry(hostname); 6 IPAddress localaddr = localhost.AddressList[0]; 7 return localaddr.ToString(); 8 }
方法時經過向網站向一些提供IP查詢的網站發送webrequest,而後分析返回的數據流
1 string strUrl = "提供IP查詢的網站的連接"; 2 Uri uri = new Uri(strUrl); 3 WebRequest webreq = WebRequest.Create(uri); 4 Stream s = webreq .GetResponse().GetResponseStream(); 5 StreamReader sr = new StreamReader(s, Encoding.Default); 6 string all = sr.ReadToEnd(); 7 int i = all.IndexOf("[") + 1; 8 //分析字符串獲得IP 9 return ip; 10 /* 11 我用的是http://www.ip.cn/getip.php?action=getip&ip_url=&from=web 12 (這種連接很容易找的,百度「IP」獲得一些網站,分析一下網站的連接就能獲得) 13 返回的數據是: 14 <div class="well"><p>當前 IP:<code>0.0.0.0</code> 來自:XX省XX市 電信</p><p>GeoIP: Beijing, China</p></div> 15 解析這段就行 16 */
⑥經過獲取CMD裏ipconfig命令的結果來獲得IP
1 private void GetIP6() 2 { 3 Process cmd = new Process(); 4 cmd.StartInfo.FileName = "ipconfig.exe";//設置程序名 5 cmd.StartInfo.Arguments = "/all"; //參數 6 //重定向標準輸出 7 cmd.StartInfo.RedirectStandardOutput = true; 8 cmd.StartInfo.RedirectStandardInput = true; 9 cmd.StartInfo.UseShellExecute = false; 10 cmd.StartInfo.CreateNoWindow = true;//不顯示窗口(控制檯程序是黑屏) 11 //cmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;//暫時不明白什麼意思 12 /* 13 收集一下 有備無患 14 關於:ProcessWindowStyle.Hidden隱藏後如何再顯示? 15 hwndWin32Host = Win32Native.FindWindow(null, win32Exinfo.windowsName); 16 Win32Native.ShowWindow(hwndWin32Host, 1); //先FindWindow找到窗口後再ShowWindow 17 */ 18 cmd.Start(); 19 string info = cmd.StandardOutput.ReadToEnd(); 20 cmd.WaitForExit(); 21 cmd.Close(); 22 textBox1.AppendText(info); 23 }
⑦NetworkInformation
如下轉自:http://www.cnblogs.com/huashanlin/archive/2007/07/07/809305.html
[STAThread]
STAThread:Single Thread Apartment Thread.(單一線程單元線程)
[]是用來表示Attributes;
[STAThread]
是一種線程模型,用在程序的入口方法上(在C#和VB.NET裏是Main()方法),來指定當前線程的ApartmentState 是STA。用在其餘方法上不產生影響。在aspx頁面上可使用AspCompat = "true" 來達到一樣的效果。這個屬性只在 Com Interop 有用,若是所有是 managed code 則無用。簡單的說法:[STAThread]指示應用程序的默認線程模型是單線程單元 (STA)。啓動線程模型可設置爲單線程單元或多線程單元。若是未對其進行設置,則該線程不被初始化。也就是說若是你用的.NET Framework,而且沒有使用COM Interop,通常不須要這個Attribute。其它的還有MTA(多線程套間)、Free Thread(自由線程)。
[STAThread] attribute指示應用程序的 COM 線程模型是單線程單元。
而於此對應的多線程單元則是 [MTAThread] (多線程單元線程)
COM 線程模型只適用於使用 COM interop 的應用程序。若是將此屬性應用到不使用 COM interop 的應用程序,將沒有任何效果。
COM 線程模型可設置爲單線程單元或多線程單元。若是應用程序線程實際調用了 COM 組件,則僅爲 COM interop 初始化該線程。若是沒有使用 COM interop,則不初始化該線程。
如下是找到的一個資料介紹:
Q. When I create a c# project from scratch in VS.NET, the generated code always have a [STAThread] attribute above the main routine. What does the STAThread attribute really do? Can I change it to MTAThread instead? I have searched website and books, no one seems to explain this well.
Asked by anon. Answered by the Wonk on February 17, 2003
A.
The STAThreadAttribute marks a thread to use the Single-Threaded COM Apartment if COM is needed. By default, .NET won't initialize COM at all. It's only when COM is needed, like when a COM object or COM Control is created or when drag 'n' drop is needed, that COM is initialized. When that happens, .NET calls the underlying CoInitializeEx function, which takes a flag indicating whether to join the thread to a multi-threaded or single-threaded apartment.
A multi-threaded apartment (MTA) in COM is more efficient, since any of a number of RPC threads from a pool can be used to handle a request. However, an object on the MTA thread needs to protect itself from multiple threads accessing it at the same time, so that efficiency comes at a cost.
The single-thread apartment (STA) in COM is inherently single-threaded and therefore no additional thread synchronization is needed. The STA is implemented using the thread's Windows message queue, which is how requests to objects on an STA are serialized. Because of how the STA thread is implemented, calls to objects on that thread are serialized with Windows message handling on that thread, making sure that everything, both the COM objects and the underlying windowing objects, e.g. HWNDs, are all synchronized. This is necessary for UI-oriented COM objects, like controls and drag 'n' drop, which must also be synchronized together with the UI.
When COM is needed .NET will call CoInitializeEx, picking the MTA by default because it's more efficient. However, to get the synchronization needed for controls, windows and drag 'n' drop, you need to mark a thread's entry point with the STAThreadAttribute to let .NET know to initialize the UI thread on the STA. All of the VS.NET project templates put that attribute in to make sure you don't forget:
大體意思是:因爲不少COM在.NET環境下若是使用多線程的話,會致使引用的COM不能正常運行,而若是不聲明程序爲STAThread的話,.NET就會自動使用多線程來提升效率,這樣就會致使不可預知的後果。
如下引用另外一同輩的發言:http://blog.csdn.net/qilang/archive/2006/06/06/775605.aspx
STA不是單線程的意思.英文爲single threaded apartment.是一種套間(或譯爲公寓)線程模式.
sta thread並不代表應用程式的類型,和應用程序不搭界,恰相反,一個應用程序能夠有多個線程.每一個線程也能夠有多個組件或對象.之前win16位系統的組件線程模式才真正是單線程.這是一種被淘汰了的模式.線程模式用於處理組件在多線程的環境裏並行與並互的方式.好比套間線程(STAThread)模式中接口跨線程傳遞必須被調度(Marshal),不調度直傳確定會失敗!而MTA或FreeThread模式中的接口能夠不經調度直接傳遞.這種調度在特定的環境中很是影響性能(可有幾百倍之差).如VB裏只支持STAThread模式.FreeThread模式的組件會在裏面表現成和跨進程同樣慢!線程模式是微軟的COM基礎中的極其重要的概念.必定要吃透!我對.net真是一竅不通(沒空去弄,對不起微軟去年的獎賞).但我能夠確定,C#中的[STAThread]屬性是應用程序的套間初始化代碼.能夠直接理解成SDK裏的CoInitialize(NULL); 初始一個STA套間其實是至關於開了一個消息窗口,全部調用經此窗口過程調度到組件內.同理[MTAThread](不知有沒有這個屬性,自已去查)能夠理解成CoInitializeEx(NULL,COINIT_MULTITHREADED )這常常是一個對初入com大門的人來講,有必定難度但必須過的一道關.