软件编程
位置:首页>> 软件编程>> C#编程>> C#移除字符串中的不可见Unicode字符 案例代码

C#移除字符串中的不可见Unicode字符 案例代码

作者:程序设计实验室  发布时间:2023-04-28 19:06:06 

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

可以看到上面那个 \u0020 在第三行第一列,是一个不可见字符,躲在标题的前面

也就是因为这个 Unicode 字符,Oracle无法正确解析,所以导致了插入数据的时候错乱了

所以破案了,就是系统前台使用人员,在输入的时候不知道咋滴搞了个Unicode字符进去&hellip;

解决方法就是我这边采集的时候再做一次过滤&hellip;

没想到C#要搞个过滤 Unicode 还挺折腾的,资料太少&hellip;

最后还是参考了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;
 }

来源:https://www.cnblogs.com/deali/p/17085516.html

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com