C#移除字符串中的不可見Unicode字符 案例代碼
C#移除字符串中的不可見Unicode字符
背景
最近發現某個數據采集的系統拿下來的數據,有些字段的JSON被莫名截斷瞭,導致後續數據分析的時候解析JSON失敗。
類似這樣
{"title": "你好
或者這樣,多瞭個雙引號啥的
{"title":""你好"}
因為數據庫是Oracle,起初以為是Oracle這老古董出問題瞭,結果一番折騰,把每條寫入數據的SQL語句都拿出來,看起來裡面的JSON格式都沒問題。
這也太詭異瞭吧,看起來沒毛病,但就為啥JSON被隨機截斷呢?
最後我試著把整段SQL放在Rider的 query console 裡面執行,然後再去數據庫裡讀取這段JSON,居然發現變成這樣瞭:
{"title":"?你好"}
啊這,看到這個大大的問號,立刻就能知道這個“你好”裡面不止是這兩個字,肯定含有不可見的Unicode字符。
然後把這段JSON復制出來,用16進制模式打開,果然看到在“你好”前面有一個 \u0020
的字符…
Unicode碼表
- 0000-007F:C0控制符及基本拉丁文 (C0 Control and Basic Latin)
- 0080-00FF:C1控制符及拉丁文補充-1 (C1 Control and Latin 1 Supplement)
- 0100-017F:拉丁文擴展-A (Latin Extended-A)
- 0180-024F:拉丁文擴展-B (Latin Extended-B)
- 0250-02AF:國際音標擴展 (IPA Extensions)
- 02B0-02FF:空白修飾字母 (Spacing Modifiers)
- ……
這裡再附上部分 Unicode 表格
U+ | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0000 | NUL | SOH | STX | ETX | EOT | ENQ | ACK | BEL | BS | HT | LF | VT | FF | CR | SO | SI |
0010 | DLE | DC1 | DC2 | DC3 | DC4 | NAK | SYN | ETB | CAN | EM | SUB | ESC | FS | GS | RS | US |
0020 | ! | " | # | $ | % | & | ' | ( | ) | * | + | , | – | . | / | |
0030 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | : | ; | < | = | > | ? |
0040 | @ | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O |
0050 | P | Q | R | S | T | U | V | W | X | Y | Z | [ | \ | ] | ^ | _ |
0060 | ` | a | b | c | d | e | f | g |
可以看到上面那個 \u0020
在第三行第一列,是一個不可見字符,躲在標題的前面
也就是因為這個 Unicode 字符,Oracle無法正確解析,所以導致瞭插入數據的時候錯亂瞭
所以破案瞭,就是系統前臺使用人員,在輸入的時候不知道咋滴搞瞭個Unicode字符進去…
解決方法就是我這邊采集的時候再做一次過濾…
沒想到C#要搞個過濾 Unicode 還挺折騰的,資料太少…
最後還是參考瞭Java的資料搞的。= =…
代碼
代碼如下
寫瞭個擴展方法來過濾
public static class StringExt { // 控制字符 private static readonly Regex ControlCharRegex = new Regex(@"[\p{C}]", RegexOptions.Compiled); /// <summary> /// 移除控制字符 /// </summary> public static string RemoveControlChars(this string text) { return ControlCharRegex.Replace(text, string.Empty); } }
要使用的時候就這樣
var outStr = "帶有Unicode的字符串".RemoveControlChars();
搞定。
參考資料
UniCode編碼表及部分不可見字符過濾方案 – https://www.cnblogs.com/fan-yuan/p/8176886.html
https://stackoverflow.com/questions/6198986/how-can-i-replace-non-printable-unicode-characters-in-java
補充:C# 字符串與unicode互相轉換實戰案例
代碼如下所示:
/// <summary> /// 字符串轉Unicode /// </summary> /// <param name="source">源字符串</param> /// <returns>Unicode編碼後的字符串</returns> public static string String2Unicode(string source) { var bytes = Encoding.Unicode.GetBytes(source); var stringBuilder = new StringBuilder(); for (var i = 0; i < bytes.Length; i += 2) { stringBuilder.AppendFormat("\\u{0:x2}{1:x2}", bytes[i + 1], bytes[i]); } return stringBuilder.ToString(); } /// <summary> /// 字符串轉為UniCode碼字符串 /// </summary> /// <param name="s"></param> /// <returns></returns> public static string StringToUnicode(string s) { char[] charbuffers = s.ToCharArray(); byte[] buffer; StringBuilder sb = new StringBuilder(); for (int i = 0; i < charbuffers.Length; i++) { buffer = System.Text.Encoding.Unicode.GetBytes(charbuffers[i].ToString()); sb.Append(String.Format("\\u{0:X2}{1:X2}", buffer[1], buffer[0])); } return sb.ToString(); } /// <summary> /// Unicode字符串轉為正常字符串 /// </summary> /// <param name="srcText"></param> /// <returns></returns> public static string UnicodeToString(string srcText) { string dst = ""; string src = srcText; int len = srcText.Length / 6; for (int i = 0; i <= len - 1; i++) { string str = ""; str = src.Substring(0, 6).Substring(2); src = src.Substring(6); byte[] bytes = new byte[2]; bytes[1] = byte.Parse(int.Parse(str.Substring(0, 2), System.Globalization.NumberStyles.HexNumber).ToString()); bytes[0] = byte.Parse(int.Parse(str.Substring(2, 2), System.Globalization.NumberStyles.HexNumber).ToString()); dst += Encoding.Unicode.GetString(bytes); } return dst; }
到此這篇關於C#移除字符串中的不可見Unicode字符 的文章就介紹到這瞭,更多相關C#移除Unicode字符 內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- C# 字符串與unicode互相轉換實戰案例
- emoji表情與unicode編碼互轉的實現(JS,JAVA,C#)
- C# string轉換為幾種不同編碼的Byte[]的問題解讀
- C# Unicode編碼解碼的實現
- C#中對象與JSON字符串互相轉換的三種方式