這幾天學習分析聲音的波形數據,接收到的是十六進制的數據,須要將數據轉換成十進制再繪圖,這個過程涉及到字符串的分割,正好能夠促進本身對C#相關知識的學習。說到分割字符串,我首先想到的是Split,但根據本例分割要求沒法直接使用,須要進行一些處理。經過比較,我以爲經常使用於截取字符串的substring函數能夠較方便的解決該問題,故記錄下來方便與你們交流、學習。(相信必定有更好的處理方法,但願各位不吝賜教)數組
一.該程序的主要目的/功能ide
原數據以下圖所示(十六進制數據):函數
原數據4byte表示一個數(即圖中第一個數是7E51,第二個是75BA……),須要將原數據學習
按指定長度(4byte)分割成新的字符串,而後轉化爲十進制的數:編碼
運行界面:spa
/*左邊文本框是十六進制的原數據,右邊是按長度爲4(byte)分割後轉化獲得的相應的十進制數*/操作系統
1 using System; 2 using System.Text; 3 using System.Windows.Forms; 4 using System.IO; 5 using System.Text.RegularExpressions; 6 7 namespace StringOperate 8 { 9 public partial class Form1 : Form 10 { 11 public Form1() 12 { 13 InitializeComponent(); 14 } 15 16 /// <summary> 17 /// 去掉字符串中的空格、回車和換行,而後按指定長度進行分割 18 /// </summary> 19 /// <param name="str">待處理的字符串</param> 20 /// <returns></returns> 21 static string[] strProcess(string str) 22 { 23 string strProcessed; 24 string pass = @"[\t\r\n\s]"; 25 strProcessed = Regex.Replace(str, pass, ""); //去掉、回車、換行、空格 26 int strLength = strProcessed.Length; //統計經處理後的字符長度 27 //判斷待處理的字符串長度是否符合要求,並給出提示 28 if (strLength % 4 != 0) 29 { 30 int absenceNum = 4-strLength % 4; 31 string notification = $"注意:請檢查數據是否完整!\r\n[提示:數據彷佛缺乏{absenceNum}位數字數符]"; 32 MessageBox.Show(notification, "Tips", MessageBoxButtons.OK, MessageBoxIcon.Information); 33 } 34 int byteLength = strProcessed.Length / 4; //統計分割後字符數組長度,數組中每一個元素長度爲四個字節 35 string[] strArrayH = new string[byteLength]; //存放十六進制字符串 36 int[] dateDecimal = new int[byteLength]; //存放轉換後的十進制數據 37 //將字符串分割爲長度爲4的字符數組 38 for (int i=0;i<(byteLength);i=i+1) 39 { 40 try 41 { 42 strArrayH[i]= strProcessed.Substring(4*i,4);//i-起始位置,4-子串長度 43 } 44 catch (Exception e) 45 { 46 MessageBox.Show(e.ToString(),"異常提示",MessageBoxButtons.OK,MessageBoxIcon.Warning); 47 continue; 48 } 49 } 50 return strArrayH; 51 } 52 53 private void 打開ToolStripMenuItem_Click(object sender, EventArgs e) 54 { 55 string mydate; 56 OpenFileDialog Ofdlg = new OpenFileDialog(); 57 openFileDialog1.Filter = "Word工做簿97-2003(*.doc)|*.doc|txt files (*.txt)|*.txt|All files (*.*)|*.*"; 58 openFileDialog1.FileName = "default"; 59 openFileDialog1.FilterIndex = 2; 60 openFileDialog1.Title = "請選擇待處理的數據文本"; //對話框的標題 61 62 if (openFileDialog1.ShowDialog()==DialogResult.OK) 63 { 64 FileStream myfile = new FileStream(openFileDialog1.FileName,FileMode.Open,FileAccess.Read); 65 //使用System.Text.Encoding.Defaul告訴StreamReader採用目前操做系統的編碼,避免出現亂碼 66 StreamReader SR = new StreamReader(myfile,Encoding.Default); 67 mydate = SR.ReadToEnd(); 68 try 69 { 70 textBox1.Text = mydate; 71 SR.Close(); 72 } 73 catch (Exception ex) 74 { 75 MessageBox.Show("打開文件出錯:" + ex.Message); 76 } 77 } 78 } 79 80 //將文本按指定長度分割 81 private void 分割字符串ToolStripMenuItem_Click(object sender, EventArgs e) 82 { 83 textBox2.Text = ""; 84 string myContentBefore; 85 string[] myContentAfter; 86 myContentBefore = textBox1.Text.Trim(); 87 myContentAfter = strProcess(myContentBefore); 88 int[] dateDecimal = new int[myContentAfter.Length]; 89 for (int i = 0; i < myContentAfter.Length; i++) 90 { 91 try 92 { 93 dateDecimal[i] = Convert.ToInt32(myContentAfter[i], 16); 94 } 95 catch (Exception ex) 96 { 97 MessageBox.Show(ex.ToString(),"提示"); 98 continue; 99 } 100 finally 101 { 102 /* 103 * textBox2.Text = (textBox2.Text + " " + dateDecimal[i].ToString()).Trim(); 104 * textBox2.Text += dateDecimal[i].ToString() + " "; 105 * 當數據較多時,上面兩種給textBox的賦值方式響應較慢,程序可能出現假死 106 * 須要頻繁更新TextBox(追加文本)時,AppendText可以穩定的即時更新,並且高效 107 */ 108 textBox2.AppendText(dateDecimal[i].ToString()+" "); 109 } 110 } 111 textBox2.Text = textBox2.Text.TrimEnd(); 112 113 } 114 115 //清空textbox1的內容 116 private void 清除text1ToolStripMenuItem_Click(object sender, EventArgs e) 117 { 118 textBox1.Text = ""; 119 } 120 121 //清空textbox2的內容 122 private void 清除text2ToolStripMenuItem_Click(object sender, EventArgs e) 123 { 124 textBox2.Text = ""; 125 } 126 127 private void 保存ToolStripMenuItem_Click(object sender, EventArgs e) 128 { 129 StreamWriter mySteam; 130 SaveFileDialog Sfdlg = new SaveFileDialog(); 131 saveFileDialog1.Filter= " Word文檔97-2003(*.doc)|*.doc|txt files(*.txt)|*.txt|Excel工做簿97-2003(*.xls)|*.xls|All files(*.*)|*.*"; 132 saveFileDialog1.FilterIndex = 2; //設置默認文件類型 133 saveFileDialog1.FileName = "default1"; //設置文件的默認名稱 134 saveFileDialog1.RestoreDirectory = true; //記憶上次打開位置 135 if (saveFileDialog1.ShowDialog()== DialogResult.OK) 136 { 137 mySteam = new StreamWriter(saveFileDialog1.FileName); 138 mySteam.Write(textBox2.Text.Trim()); 139 //使用Flush()方法將全部信息從基礎緩衝區移動到其目標或清除緩衝區,或者同時執行這兩種操做 140 mySteam.Flush(); 141 mySteam.Close(); 142 } 143 } 144 } 145 }
1.分割字符串——Substring(int startIndex, int length).net
因爲須要按4個字節長度來分割字符串,而原數據是每兩個字節就有一個空格,因此沒法直接經過Split方法進行分割。我想到了兩種思路:①去掉第一、三、五、7……個空格以及回車、換行和製表字符,而後使用Split分割字符串;②去掉全部空格、回車、換行和製表符,而後經過循環取字符串的子串的方式而達到‘分割’字符串到字符數組的目的。我以爲第二種方法的思路更簡單,因此採用的是第二種方法。(int startIndex——開始截取子串的位置,int length——子字符串的長度)code
2.數據訪問——openFileDialog & saveFileDialogorm
博客園介紹這方面知識的的文章不少,寫的也很是好,這裏就再也不贅述。
3.Convert類 ——ToInt32(string,IFormatProvider)
使用指定的區域性特定格式信息,將數字的指定 String 表示形式轉換爲等效的 32 位有符號整數。如本例中Convert.ToInt32(string,16)——把十六進制的數字的字符串轉換爲效的 32 位有符號整數(十進制)。詳細用法可參考Microsoft官網的.net開發文檔:Convert類,Convert.ToInt32(string,IFormatProvider)方法。
寫得比較匆忙,歡迎你們批評指正。