雖然Silverlight已經是被拋棄的孩子了,但此前做的一些項目還是用到Silverlight。今天用Silverlight導入客戶端本地的一個txt文件,然后讀取需要的信息。隨手記錄一下,留作以后備忘。
網上也有不少的相關資料,但好像要么是單純的Ctrl+C、Ctrl+V,要么是不夠齊全。閑話少說,直接上代碼。
我用的是MVVM模式,所以用RelayCommand命令打開了。其它的,直接在類似Button_Click事件里調用OpenFile(),同理。
1 /// <summary> 2 /// 打開文件 3 /// </summary> 4 private void OpenFile() 5 { 6 try 7 { 8 //檢查是否是在OOB模式下運行 9 OOBChecker.CheckInstallState(() => 10 { 11 //彈出選擇文件對話框 12 OpenFileDialog fileDialog = new OpenFileDialog() 13 { 14 Filter = "Txt Files (*.txt)|*.txt|All Files (*.*)|*.*", 15 }; 16 17 if (fileDialog.ShowDialog() == true) 18 { 19 //讀取文件流 20 using (Stream fs = fileDialog.File.OpenRead()) 21 { 22 ReadTxtFile(fs); 23 fs.Close(); 24 } 25 } 26 }); 27 } 28 catch (Exception e) 29 { 30 31 //錯誤處理 32 } 33 }
注: OOBChecker.CheckInstallState,是為公司項目需要寫的一個檢查Silverlight程序是否在瀏覽器外運行的方法。眾所周知,Silverlight是可以安裝在本機脫離瀏覽器運行的,這樣便可獲得更高的執行權限。有時對本地文件(夾)進行操作時,程序需要獲得信任權限。不知是否我瀏覽器設置問題,我直接在IE上運行,貌似也有權限。
附上OOBChecker的代碼。
public class OOBChecker { /// <summary> /// 當前程序是否安裝在本地 /// </summary> private static bool IsInstall { get; set; } /// <summary> /// 檢查當前程序有沒有安裝在本地,callback是回調 /// </summary> public static void CheckInstallState(Action callback) { try { if (App.Current.HasElevatedPermissions) { //跳過OOB驗證,直接在網頁打開 if (callback != null) { callback(); return; } } if (App.Current.InstallState == InstallState.Installed) { if (App.Current.IsRunningOutOfBrowser) { IsInstall = true; //項目中操作Office COM需要 if (AutomationFactory.IsAvailable) { if (callback != null) { callback(); } } else { MessageWindow.CreateNew("您好,AutomationFactory IsAvailable Is False", resTipInformation.strApplicationTitle); } //App.Current.MainWindow.TopMost = true; } else { MessageWindow.CreateNew("您好,您已在本機安裝了模塊程序,請保存本頁面數據后雙擊運行桌面的圖標。", resTipInformation.strApplicationTitle); } } else { MessageWindow.CreateNewConfirm("打開文檔之前需要安裝本程序在您電腦上,確定幫您安裝嗎?為避免數據丟失,請確認前先保存數據。", resTipInformation.strApplicationTitle, () => { App.Current.InstallStateChanged += Current_InstallStateChanged; App.Current.Install(); }); } } catch (Exception ex) { ErrorWindow.CreateNew(ex); Debug.WriteLine(string.Format("{0} at {1}", ex.Message, "OOBChecker")); } } /// <summary> /// 安裝完成后 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void Current_InstallStateChanged(object sender, System.EventArgs e) { if (App.Current.InstallState == InstallState.Installed) { IsInstall = true; } } }
OpenFile方法中,調用了一個讀取文件內容的方法:ReadTxtFile
1 /// <summary> 2 /// 一行行地循環讀取 3 /// </summary> 4 private void ReadTxtFile(Stream fs) 5 { 6 var myTable = new List<string>(); 7 using (StreamReader reader = new StreamReader(fs, new Gb2312Encoding())) 8 { 9 /* 10 * 一次性讀出所有文件信息 11 * var fileText = string.Empty; 12 fileText = reader.ReadToEnd(); 13 */ 14 15 reader.BaseStream.Seek(0, SeekOrigin.Begin); 16 string strLine = reader.ReadLine(); 17 var tableIndex = 0; 18 while (strLine != null) 19 { 20 /* 21 * do your things here 22 if (strLine.Contains("[Your message is here]")) 23 { 24 //找到表頭了 25 tableIndex++; 26 } 27 28 if (tableIndex > 6) 29 { 30 //讀完需要的表信息了,跳出 31 break; 32 } 33 34 if (tableIndex >= 4) 35 { 36 //開始獲取需要的信息 37 myTable.Add(strLine); 38 } 39 if (tableIndex > 0) 40 { 41 tableIndex++; 42 } 43 */ 44 strLine = reader.ReadLine(); 45 } 46 reader.Close(); 47 } 48 49 if (myTable.Any()) 50 { 51 foreach (var strItem in myTable) 52 { 53 var view = strItem.TrimEnd('\t').Split('\t'); 54 //do something here 55 } 56 } 57 58 }
注:Silverlight不支持GB2312編碼,所以打開中文時會亂碼。為此,我們可以繼承Encoding,自己為程序添加GB2312編碼。然后像下面那樣調用。
StreamReader reader = new StreamReader(fs, new Gb2312Encoding())
Gb2312Encoding的代碼,里面包含了個Gb2312toUnicodeDictinary(這個是網上找的,很多網上資料只有Gb2312Encoding,卻沒有附上Gb2312toUnicodeDictinary)。
只上Gb2312Encoding的代碼吧,Gb2312toUnicodeDictinary有7000多行的說……,這兩個文件以附件形式放在后面,有需要的童鞋自行下載。
1 public class Gb2312Encoding : Encoding 2 { 3 public override string WebName 4 { 5 get 6 { 7 return "gb2312"; 8 } 9 } 10 11 public Gb2312Encoding() 12 { 13 14 } 15 public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex) 16 { 17 throw new NotImplementedException(); 18 } 19 20 public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) 21 { 22 int j = 0; 23 char c; 24 for (int i = 0; i < byteCount; i += 2) 25 { 26 if (i + 1 >= bytes.Length) 27 { 28 char[] last = Encoding.UTF8.GetChars(new byte[] { bytes[i] }); 29 chars[j] = last[0]; 30 } 31 else 32 { 33 byte[] bb = new byte[] { bytes[i], bytes[i + 1] }; 34 if (Gb2312toUnicodeDictinary.TryGetChar(bb, out c)) 35 { 36 chars[j] = c; 37 j++; 38 } 39 else 40 { 41 char[] tt = Encoding.UTF8.GetChars(new byte[] { bb[1] }); 42 chars[j] = tt[0]; 43 j++; 44 //測試下一個 45 if (i + 2 >= bytes.Length) 46 { 47 char[] tttt = Encoding.UTF8.GetChars(new byte[] { bb[0] }); 48 chars[j] = tttt[0]; 49 j++; 50 } 51 else 52 { 53 byte[] test = new byte[] { bb[0], bytes[i + 2] }; 54 if (Gb2312toUnicodeDictinary.TryGetChar(test, out c)) 55 { 56 chars[j] = c; 57 j++; 58 i++; 59 } 60 else 61 { 62 char[] ttt = Encoding.UTF8.GetChars(new byte[] { bb[0] }); 63 chars[j] = ttt[0]; 64 j++; 65 } 66 67 } 68 } 69 } 70 } 71 72 return chars.Length; 73 } 74 75 public override int GetByteCount(char[] chars, int index, int count) 76 { 77 return count; 78 } 79 public override int GetCharCount(byte[] bytes, int index, int count) 80 { 81 return count; 82 } 83 84 public override int GetMaxByteCount(int charCount) 85 { 86 return charCount; 87 } 88 public override int GetMaxCharCount(int byteCount) 89 { 90 return byteCount; 91 } 92 public static int CharacterCount 93 { 94 get { return 7426; } 95 } 96 }
