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!

推薦閱讀: