首頁 > 軟體

C#移除字串中的不可見Unicode字元 案例程式碼

2023-09-12 18:04:03

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+0123456789ABCDEF
0000NULSOHSTXETXEOTENQACKBELBSHTLFVTFFCRSOSI
0010DLEDC1DC2DC3DC4NAKSYNETBCANEMSUBESCFSGSRSUS
0020!"#$%&'()*+,-./
00300123456789:;<=>?
0040@ABCDEFGHIJKLMNO
0050PQRSTUVWXYZ[]^_
0060`abcdefg

可以看到上面那個 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字元 內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com