查看: 892|回复: 0

[ASP.NET教程] C#按指定长度分割字符串

发表于 2018-3-22 08:00:01

  这几天学习分析声音的波形数据,接收到的是十六进制的数据,需要将数据转换成十进制再绘图,这个过程涉及到字符串的分割,正好可以促进自己对C#相关知识的学习。说到分割字符串,我首先想到的是Split,但根据本例分割要求无法直接使用,需要进行一些处理。通过比较,我觉得常用于截取字符串的substring函数可以较方便的解决该问题,故记录下来方便与大家交流、学习。(相信一定有更好的处理方法,希望各位不吝赐教)


一.该程序的主要目的/功能

原数据如下图所示(十六进制数据):

原数据4byte表示一个数(即图中第一个数是7E51,第二个是75BA……),需要将原数据

按指定长度(4byte)分割成新的字符串,然后转化为十进制的数:

运行界面:

/*左边文本框是十六进制的原数据,右边是按长度为4(byte)分割后转化得到的相应的十进制数*/

二.程序代码
  1. 1 using System;
  2. 2 using System.Text;
  3. 3 using System.Windows.Forms;
  4. 4 using System.IO;
  5. 5 using System.Text.RegularExpressions;
  6. 6
  7. 7 namespace StringOperate
  8. 8 {
  9. 9 public partial class Form1 : Form
  10. 10 {
  11. 11 public Form1()
  12. 12 {
  13. 13 InitializeComponent();
  14. 14 }
  15. 15
  16. 16 /// <summary>
  17. 17 /// 去掉字符串中的空格、回车和换行,然后按指定长度进行分割
  18. 18 /// </summary>
  19. 19 /// <param name="str">待处理的字符串</param>
  20. 20 /// <returns></returns>
  21. 21 static string[] strProcess(string str)
  22. 22 {
  23. 23 string strProcessed;
  24. 24 string pass = @"[\t\r\n\s]";
  25. 25 strProcessed = Regex.Replace(str, pass, ""); //去掉、回车、换行、空格
  26. 26 int strLength = strProcessed.Length; //统计经处理后的字符长度
  27. 27 //判断待处理的字符串长度是否符合要求,并给出提示
  28. 28 if (strLength % 4 != 0)
  29. 29 {
  30. 30 int absenceNum = 4-strLength % 4;
  31. 31 string notification = $"注意:请检查数据是否完整!\r\n[提示:数据似乎缺少{absenceNum}位数字数符]";
  32. 32 MessageBox.Show(notification, "Tips", MessageBoxButtons.OK, MessageBoxIcon.Information);
  33. 33 }
  34. 34 int byteLength = strProcessed.Length / 4; //统计分割后字符数组长度,数组中每个元素长度为四个字节
  35. 35 string[] strArrayH = new string[byteLength]; //存放十六进制字符串
  36. 36 int[] dateDecimal = new int[byteLength]; //存放转换后的十进制数据
  37. 37 //将字符串分割为长度为4的字符数组
  38. 38 for (int i=0;i<(byteLength);i=i+1)
  39. 39 {
  40. 40 try
  41. 41 {
  42. 42 strArrayH[i]= strProcessed.Substring(4*i,4);//i-起始位置,4-子串长度
  43. 43 }
  44. 44 catch (Exception e)
  45. 45 {
  46. 46 MessageBox.Show(e.ToString(),"异常提示",MessageBoxButtons.OK,MessageBoxIcon.Warning);
  47. 47 continue;
  48. 48 }
  49. 49 }
  50. 50 return strArrayH;
  51. 51 }
  52. 52
  53. 53 private void 打开ToolStripMenuItem_Click(object sender, EventArgs e)
  54. 54 {
  55. 55 string mydate;
  56. 56 OpenFileDialog Ofdlg = new OpenFileDialog();
  57. 57 openFileDialog1.Filter = "Word工作簿97-2003(*.doc)|*.doc|txt files (*.txt)|*.txt|All files (*.*)|*.*";
  58. 58 openFileDialog1.FileName = "default";
  59. 59 openFileDialog1.FilterIndex = 2;
  60. 60 openFileDialog1.Title = "请选择待处理的数据文本"; //对话框的标题
  61. 61
  62. 62 if (openFileDialog1.ShowDialog()==DialogResult.OK)
  63. 63 {
  64. 64 FileStream myfile = new FileStream(openFileDialog1.FileName,FileMode.Open,FileAccess.Read);
  65. 65 //使用System.Text.Encoding.Defaul告诉StreamReader采用目前操作系统的编码,避免出现乱码
  66. 66 StreamReader SR = new StreamReader(myfile,Encoding.Default);
  67. 67 mydate = SR.ReadToEnd();
  68. 68 try
  69. 69 {
  70. 70 textBox1.Text = mydate;
  71. 71 SR.Close();
  72. 72 }
  73. 73 catch (Exception ex)
  74. 74 {
  75. 75 MessageBox.Show("打开文件出错:" + ex.Message);
  76. 76 }
  77. 77 }
  78. 78 }
  79. 79
  80. 80 //将文本按指定长度分割
  81. 81 private void 分割字符串ToolStripMenuItem_Click(object sender, EventArgs e)
  82. 82 {
  83. 83 textBox2.Text = "";
  84. 84 string myContentBefore;
  85. 85 string[] myContentAfter;
  86. 86 myContentBefore = textBox1.Text.Trim();
  87. 87 myContentAfter = strProcess(myContentBefore);
  88. 88 int[] dateDecimal = new int[myContentAfter.Length];
  89. 89 for (int i = 0; i < myContentAfter.Length; i++)
  90. 90 {
  91. 91 try
  92. 92 {
  93. 93 dateDecimal[i] = Convert.ToInt32(myContentAfter[i], 16);
  94. 94 }
  95. 95 catch (Exception ex)
  96. 96 {
  97. 97 MessageBox.Show(ex.ToString(),"提示");
  98. 98 continue;
  99. 99 }
  100. 100 finally
  101. 101 {
  102. 102 /*
  103. 103 * textBox2.Text = (textBox2.Text + " " + dateDecimal[i].ToString()).Trim();
  104. 104 * textBox2.Text += dateDecimal[i].ToString() + " ";
  105. 105 * 当数据较多时,上面两种给textBox的赋值方式响应较慢,程序可能出现假死
  106. 106 * 需要频繁更新TextBox(追加文本)时,AppendText能够稳定的即时更新,而且高效
  107. 107 */
  108. 108 textBox2.AppendText(dateDecimal[i].ToString()+" ");
  109. 109 }
  110. 110 }
  111. 111 textBox2.Text = textBox2.Text.TrimEnd();
  112. 112
  113. 113 }
  114. 114
  115. 115 //清空textbox1的内容
  116. 116 private void 清除text1ToolStripMenuItem_Click(object sender, EventArgs e)
  117. 117 {
  118. 118 textBox1.Text = "";
  119. 119 }
  120. 120
  121. 121 //清空textbox2的内容
  122. 122 private void 清除text2ToolStripMenuItem_Click(object sender, EventArgs e)
  123. 123 {
  124. 124 textBox2.Text = "";
  125. 125 }
  126. 126
  127. 127 private void 保存ToolStripMenuItem_Click(object sender, EventArgs e)
  128. 128 {
  129. 129 StreamWriter mySteam;
  130. 130 SaveFileDialog Sfdlg = new SaveFileDialog();
  131. 131 saveFileDialog1.Filter= " Word文档97-2003(*.doc)|*.doc|txt files(*.txt)|*.txt|Excel工作簿97-2003(*.xls)|*.xls|All files(*.*)|*.*";
  132. 132 saveFileDialog1.FilterIndex = 2; //设置默认文件类型
  133. 133 saveFileDialog1.FileName = "default1"; //设置文件的默认名称
  134. 134 saveFileDialog1.RestoreDirectory = true; //记忆上次打开位置
  135. 135 if (saveFileDialog1.ShowDialog()== DialogResult.OK)
  136. 136 {
  137. 137 mySteam = new StreamWriter(saveFileDialog1.FileName);
  138. 138 mySteam.Write(textBox2.Text.Trim());
  139. 139 //使用Flush()方法将所有信息从基础缓冲区移动到其目标或清除缓冲区,或者同时执行这两种操作
  140. 140 mySteam.Flush();
  141. 141 mySteam.Close();
  142. 142 }
  143. 143 }
  144. 144 }
  145. 145 }
复制代码
View Code 三.涉及的知识点

1.分割字符串——Substring(int startIndex, int length)

  由于需要按4个字节长度来分割字符串,而原数据是每两个字节就有一个空格,所以无法直接通过Split方法进行分割。我想到了两种思路:①去掉第1、3、5、7……个空格以及回车、换行和制表字符,然后使用Split分割字符串;②去掉所有空格、回车、换行和制表符,然后通过循环取字符串的子串的方式而达到‘分割’字符串到字符数组的目的。我觉得第二种方法的思路更简单,所以采用的是第二种方法。(int startIndex——开始截取子串的位置,int length——子字符串的长度)

2.数据访问——openFileDialog & saveFileDialog

  博客园介绍这方面知识的的文章很多,写的也非常好,这里就不再赘述。

3.Convert类 ——ToInt32(string,IFormatProvider)

  使用指定的区域性特定格式信息,将数字的指定 String 表示形式转换为等效的 32 位有符号整数。如本例中Convert.ToInt32(string,16)——把十六进制的数字的字符串转换为效的 32 位有符号整数(十进制)。详细用法可参考Microsoft官网的.net开发文档:Convert类,Convert.ToInt32(string,IFormatProvider)方法。

  写得比较匆忙,欢迎大家批评指正。



回复

使用道具 举报