Form1.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10. using System.IO;
  11. using log = Log.Log;
  12. using Excel = Microsoft.Office.Interop.Excel;
  13. using System.Threading;
  14. namespace frequency
  15. {
  16. public partial class Form1 : Form
  17. {
  18. public long currentIndex;
  19. public long totalNum;
  20. public Dictionary<string, int> finalResult;
  21. public Form1()
  22. {
  23. // init logger
  24. log.Init("frequency.log");
  25. // init params
  26. path = System.Environment.CurrentDirectory;
  27. // init component
  28. InitializeComponent();
  29. // init ShowProgress
  30. Thread.Sleep(1000);
  31. Thread thread = new Thread(this.ShowProgress);
  32. thread.IsBackground = true;
  33. thread.Start();
  34. }
  35. private string[] originTextsOrder;
  36. private string[] originTextsInverse;
  37. private string[] targetTexts;
  38. // progress status
  39. const string CAL_WAIT = "wait";
  40. const string CAL_RUNNING = "running";
  41. const string CAL_ERROR = "error";
  42. const string CAL_SUCCESS = "success";
  43. const string CAL_EXPORT = "exporting";
  44. public delegate void ChangeProgressStatus();
  45. public delegate void CallBackDelegate();
  46. private void SelectOriginButton(object sender, EventArgs e)
  47. {
  48. var fileDialog = new OpenFileDialog();
  49. fileDialog.Multiselect = false;
  50. fileDialog.Title = "选择源文件";
  51. if (fileDialog.ShowDialog() == DialogResult.OK)
  52. {
  53. this.originTextPath = fileDialog.FileName;
  54. this.originText.Text = originTextPath;
  55. }
  56. }
  57. private void ShowOriginText(object sender, EventArgs e)
  58. {
  59. }
  60. private void SelectTargetButton(object sender, EventArgs e)
  61. {
  62. var fileDialog = new OpenFileDialog();
  63. fileDialog.Multiselect = false;
  64. fileDialog.Title = "选择目标文件";
  65. if (fileDialog.ShowDialog() == DialogResult.OK)
  66. {
  67. this.targetTextPath = fileDialog.FileName;
  68. this.targetText.Text = this.targetTextPath;
  69. }
  70. }
  71. private void ShowTargetText(object sender, EventArgs e)
  72. {
  73. }
  74. private void Calculate_Click(object sender, EventArgs e)
  75. {
  76. if (null == this.originTextPath || null == this.targetTextPath || "" == this.originTextPath.Trim() || "" == this.targetTextPath.Trim())
  77. {
  78. MessageBox.Show("请先选择文件");
  79. return;
  80. }
  81. //this.progress.Text = "计算中...";
  82. //this.progress.Refresh();
  83. this.progressStatus = CAL_RUNNING;
  84. this.calculate.Enabled = false;
  85. var code = this.Calculate();
  86. Application.DoEvents();
  87. }
  88. private int Calculate()
  89. {
  90. int code;
  91. // read origin file
  92. code = this.ReadOriginText();
  93. if (code != 0)
  94. {
  95. log.E("Calculate_Click read origin file error with code: {0}", code);
  96. return 1;
  97. }
  98. // read target file
  99. code = this.ReadTargetText();
  100. if (code != 0)
  101. {
  102. log.E("Calculate_Click read target file error with code: {0}", code);
  103. return 1;
  104. }
  105. // clear target file
  106. this.CleanTarget();
  107. // look up
  108. Thread runLoopUp = new Thread(Lookup);
  109. CallBackDelegate cbd = LoopUpCallBack;
  110. runLoopUp.Start(cbd);
  111. log.D("Calculate_Click look up success");
  112. // write data to file
  113. //this.progress.Text = "导出数据中...";
  114. //this.progress.Refresh();
  115. //this.progressStatus = CAL_EXPORT;
  116. //var msg = this.Write2Xlsx(result);
  117. //if ("" != msg)
  118. //{
  119. // log.E("Calculate_Click write data to xlsx error: {0}", msg);
  120. // return 1;
  121. //}
  122. log.D("Calculate_Click write data to xlsx success");
  123. return 0;
  124. }
  125. private void LoopUpCallBack()
  126. {
  127. progressStatus = CAL_EXPORT;
  128. var msg = this.Write2Xlsx(finalResult);
  129. if ("" != msg)
  130. {
  131. progressStatus = CAL_ERROR;
  132. calculate.Enabled = true;
  133. log.E("Calculate_Click write data to xlsx error: {0}", msg);
  134. return ;
  135. }
  136. progressStatus = CAL_SUCCESS;
  137. log.D("Calculate_Click write data to xlsx success with length: {0}", finalResult.Count);
  138. }
  139. private void SeeResult_Click(object sender, EventArgs e)
  140. {
  141. try
  142. {
  143. System.Diagnostics.Process.Start("explorer.exe", path);
  144. }
  145. catch (Exception err)
  146. {
  147. MessageBox.Show(err.ToString());
  148. }
  149. }
  150. // 读取原始文件
  151. private int ReadOriginText()
  152. {
  153. string[] texts;
  154. try
  155. {
  156. texts = File.ReadAllLines(this.originTextPath);
  157. }
  158. catch (Exception err)
  159. {
  160. log.E("readOriginText with path: {0} error: {1}", this.originTextPath, err.ToString());
  161. MessageBox.Show(err.ToString());
  162. return 1;
  163. }
  164. if (texts.Length < 1)
  165. {
  166. log.E("readOriginText with path: {0}, read file is empty", this.originTextPath);
  167. MessageBox.Show("file is empty");
  168. return 1;
  169. }
  170. log.D("ReadOriginText received origin text with length: {0}", texts.Length);
  171. // check
  172. int length = 0;
  173. for (int i = 0; i < texts.Length; i++)
  174. {
  175. var val = texts[i].Trim();
  176. if (val.Length < 1)
  177. {
  178. continue;
  179. }
  180. length++;
  181. }
  182. log.D("ReadOriginText received check text with length: {0}", length);
  183. // append
  184. var tempTexts = new string[length];
  185. int index = 0;
  186. for (int i = 0; i < texts.Length; i++)
  187. {
  188. var val = texts[i].Trim();
  189. if (val.Length < 1)
  190. {
  191. continue;
  192. }
  193. tempTexts[index++] = texts[i];
  194. }
  195. // combine
  196. index = 0;
  197. this.originTextsOrder = new string[(length * (length - 1)) / 2];
  198. for (int i = 0; i < length; i++)
  199. {
  200. for (int j = i + 1; j < length; j++)
  201. {
  202. this.originTextsOrder[index++] = tempTexts[i] + "-" + tempTexts[j];
  203. }
  204. }
  205. index = 0;
  206. this.originTextsInverse = new string[(length * (length - 1)) / 2];
  207. for (int i = length - 1; i >= 0; i--)
  208. {
  209. for (int j = i - 1; j >= 0; j--)
  210. {
  211. this.originTextsInverse[index++] = tempTexts[i] + "-" + tempTexts[j];
  212. }
  213. }
  214. log.D("ReadOriginText read origin file success with order length: {0}, inverse length; {1}", this.originTextsOrder.Length, this.originTextsInverse.Length);
  215. return 0;
  216. }
  217. // 读取目标文件
  218. private int ReadTargetText()
  219. {
  220. string[] texts;
  221. try
  222. {
  223. texts = File.ReadAllLines(this.targetTextPath);
  224. }
  225. catch (Exception err)
  226. {
  227. log.E("ReadTargetText with path: {0} error: {1}", this.targetTextPath, err.ToString());
  228. MessageBox.Show(err.ToString());
  229. return 1;
  230. }
  231. if (texts.Length < 1)
  232. {
  233. log.E("ReadTargetText with path: {0}, read file is empty", this.targetTextPath);
  234. MessageBox.Show("file is empty");
  235. return 1;
  236. }
  237. log.D("ReadTargetText read texts: {0}", texts);
  238. // check
  239. int length = 0;
  240. for (int i = 0; i < texts.Length; i++)
  241. {
  242. var val = texts[i].Trim();
  243. if (val.Length < 1 || !val.Contains("-"))
  244. {
  245. continue;
  246. }
  247. length++;
  248. }
  249. // append
  250. this.targetTexts = new string[length];
  251. var index = 0;
  252. for (int i = 0; i < texts.Length; i++)
  253. {
  254. var val = texts[i].Trim();
  255. if (val.Length < 1 || !val.Contains("-"))
  256. {
  257. continue;
  258. }
  259. this.targetTexts[index++] = texts[i];
  260. }
  261. return 0;
  262. }
  263. /*
  264. * desc
  265. * 1. 目标文件中的字符串形如54#01(100#)--54#02,其中括号以及括号的内容清除不计。
  266. * 2. 源文件两两组合的后的字符串再到目标文件中查找,所有单个的字符串都可以忽略不计算;如58#01可以忽略不计。
  267. */
  268. private void CleanTarget()
  269. {
  270. var originLength = this.targetTexts.Length;
  271. string[] tempStrings = new string[this.targetTexts.Length];
  272. var index = 0;
  273. for (int i = 0; i < this.targetTexts.Length; i++)
  274. {
  275. var val = this.targetTexts[i].Trim();
  276. if (val.Length < 1)
  277. {
  278. continue;
  279. }
  280. if (!val.Contains("-"))
  281. {
  282. continue;
  283. }
  284. var clearStr = ClearString(val);
  285. tempStrings[index++] = clearStr;
  286. }
  287. this.targetTexts = new string[index];
  288. for (int i = 0; i < index; i++)
  289. {
  290. this.targetTexts[i] = tempStrings[i];
  291. }
  292. log.D("CleanTarget clean target origin length {0} success with last length: {1}", originLength, this.targetTexts.Length);
  293. }
  294. private string ClearString(string str)
  295. {
  296. if (!str.Contains("("))
  297. {
  298. return str;
  299. }
  300. string result = "";
  301. bool had = false;
  302. for (int i = 0; i < str.Length; i++)
  303. {
  304. if (had && str[i] != ')')
  305. {
  306. continue;
  307. }
  308. if (had && str[i] == ')')
  309. {
  310. had = false;
  311. continue;
  312. }
  313. if (str[i] == '(')
  314. {
  315. had = true;
  316. continue;
  317. }
  318. result += str[i];
  319. }
  320. return ClearString(result);
  321. }
  322. private void Lookup(object o)
  323. {
  324. this.currentIndex = 0;
  325. this.totalNum = this.targetTexts.Length * this.originTextsOrder.Length + this.originTextsInverse.Length * this.targetTexts.Length;
  326. Dictionary<string, int> result = new Dictionary<string, int>();
  327. for (int i = 0; i < this.originTextsOrder.Length; i++)
  328. {
  329. for (int j = 0; j < this.targetTexts.Length; j++)
  330. {
  331. this.currentIndex++;
  332. if (judge(this.originTextsOrder[i], this.targetTexts[j]))
  333. {
  334. var key = this.originTextsOrder[i];
  335. if (result.ContainsKey(key))
  336. {
  337. result[key] = result[key] + 1;
  338. }
  339. else
  340. {
  341. result[key] = 1;
  342. }
  343. }
  344. }
  345. }
  346. for (int i = 0; i < this.originTextsInverse.Length; i++)
  347. {
  348. for (int j = 0; j < this.targetTexts.Length; j++)
  349. {
  350. this.currentIndex++;
  351. if (judge(this.originTextsInverse[i], this.targetTexts[j]))
  352. {
  353. var key = this.originTextsInverse[i];
  354. if (result.ContainsKey(key))
  355. {
  356. result[key] = result[key] + 1;
  357. }
  358. else
  359. {
  360. result[key] = 1;
  361. }
  362. }
  363. }
  364. }
  365. finalResult = result;
  366. log.D("Lookup calcate success with length: {0}", result.Count);
  367. var cbd = o as CallBackDelegate;
  368. cbd();
  369. return ;
  370. }
  371. private bool judge(string origin, string target)
  372. {
  373. var strs = origin.Split(new char[] { '-' }, 2, StringSplitOptions.None);
  374. if (strs.Length < 2)
  375. {
  376. return false;
  377. }
  378. var originStr1 = strs[0] + "-" + strs[1];
  379. var originStr2 = strs[0] + "--" + strs[1];
  380. if (judgeDetail(originStr1, target))
  381. {
  382. return true;
  383. } else if(judgeDetail(originStr2, target))
  384. {
  385. return true;
  386. }
  387. return false;
  388. }
  389. /*
  390. * 解决形如 ea#b-c#d 中查找a#b-c#d,但是返回true的bug
  391. */
  392. private bool judgeDetail(string origin, string target)
  393. {
  394. var index = target.IndexOf(origin);
  395. if (index < 0)
  396. {
  397. return false;
  398. }
  399. if (index != 0)
  400. {
  401. if ('-' != target[index - 1])
  402. {
  403. return false;
  404. }
  405. }
  406. if (index + origin.Length < target.Length)
  407. {
  408. if ('-' != target[index + origin.Length])
  409. {
  410. return false;
  411. }
  412. }
  413. return true;
  414. }
  415. private void label1_Click(object sender, EventArgs e)
  416. {
  417. }
  418. private string Write2Xlsx(Dictionary<string, int> data)
  419. {
  420. var suffix = DateTime.Now.ToString("yyyy-MM-dd-HH-mm") + ".xlsx";
  421. var filename = Path.Combine(path, suffix);
  422. Excel.Application app = new Excel.Application();
  423. Excel.Workbook doc = app.Workbooks.Add(Type.Missing);
  424. if (doc.Worksheets.Count < 1)
  425. {
  426. doc.Worksheets.Add(Type.Missing, Type.Missing, Type.Missing);
  427. }
  428. Excel.Worksheet sheet = doc.ActiveSheet;
  429. var index = 1;
  430. foreach (var val in data)
  431. {
  432. sheet.Cells[index, 1] = val.Key;
  433. sheet.Cells[index, 2] = val.Value;
  434. index++;
  435. }
  436. try
  437. {
  438. sheet.SaveAs(filename);
  439. doc.Save();
  440. doc.Close(Type.Missing, filename, Type.Missing);
  441. app.Quit();
  442. }
  443. catch (Exception err)
  444. {
  445. log.E("Write2Xlsx write file({0}) error: {1}", filename, err.ToString());
  446. return err.ToString();
  447. }
  448. log.D("Write2Xlsx write file({0}) success", filename);
  449. return "";
  450. }
  451. private void button1_Click(object sender, EventArgs e)
  452. {
  453. //this.Write2Xlsx();
  454. }
  455. private void Form1_Load(object sender, EventArgs e)
  456. {
  457. }
  458. private void ShowProgress()
  459. {
  460. log.D("ShowProgress start successful");
  461. while (true)
  462. {
  463. if (this.IsHandleCreated)
  464. {
  465. Invoke(new ChangeProgressStatus(ChangeStatus));
  466. }
  467. //log.D("currentIndex: {0}, totalNum: {1}", currentIndex, totalNum);
  468. Thread.Sleep(1000);
  469. }
  470. log.D("ShowProgress had finished");
  471. }
  472. private void ChangeStatus()
  473. {
  474. string status = "";
  475. if (CAL_WAIT == progressStatus || "" == progressStatus)
  476. {
  477. status = "计算未开始";
  478. }
  479. if (CAL_RUNNING == progressStatus)
  480. {
  481. status = string.Format("计算中... {0}/{1}", currentIndex, totalNum);
  482. }
  483. if (CAL_ERROR == progressStatus)
  484. {
  485. status = "计算出错";
  486. }
  487. if (CAL_EXPORT == progressStatus)
  488. {
  489. status = "导出数据中...";
  490. }
  491. if (CAL_SUCCESS == progressStatus)
  492. {
  493. status = "计算完成";
  494. }
  495. this.progress.Text = status;
  496. this.progress.Refresh();
  497. if (progressStatus == CAL_ERROR || progressStatus == CAL_SUCCESS)
  498. {
  499. this.calculate.Enabled = true;
  500. this.calculate.Refresh();
  501. }
  502. }
  503. private void Form1_FormClosing(object sender, FormClosingEventArgs e)
  504. {
  505. System.Environment.Exit(0);
  506. }
  507. }
  508. }