zoukankan      html  css  js  c++  java
  • UTF-8编码中的特殊空格之C2 A0 -> NO-BREAK SPACE

    异常数据追踪

    最近发现数据库中的一个字段值数据异常的问题,业务场景中不允许这个字符串字段中出现空格,但是发现有部分数据依然有'空格',反复验证过之后发现自己写的代码的的确确会把空格trim掉,反复调试后发现代码没有问题,但是什么情况使得这些数据逃过了业务代码的校验?

    准备破案

    难道我肉眼看到的'空格',不是我们平常见到或者理解的'空格'?

    带着这个疑问,我搜索了一下相关的问题,发现果不其然,很多人都遇到了C2 A0这个不可见字符,那么这个字符到底是什么呢?

    打开UTF-8的编码表,https://www.utf8-chartable.de/unicode-utf8-table.pl?utf8=dec 找到对应的字符

    首先明确C2 A0代表的编码序号是多少,很显然我们只需要将这个十六进制转为十进制,即C2=194 A0=160,这个在编码表中对应的是

    U+00A0   194 160 NO-BREAK SPACE

    而我们一般意义上将的空格的编码是32

    U+0020   32 SPACE

    那们我们通过代码来模拟一下上面两个字符

    普通的空格 Unicode code point为U+0020即32

    C2 A0空格 Unicode code point为U+00A0即160

    找到原因之后,我们想办法把这种C2 A0空格给去除掉

    源代码见下 

    package com.lingyejun.dating.chap11;
    
    import java.nio.charset.StandardCharsets;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    public class SpecialSpace {
    
        public static void main(String[] args) {
            String str1 = "lingyejun ";
            byte[] str1Bytes = str1.getBytes();
            String space = new String(str1Bytes, StandardCharsets.UTF_8);
            System.out.println("带有32 Space的字符串:" + space);
            System.out.println("使用trim去掉32 -> Space:" + space.trim());
    
            byte[] str2Bytes = new byte[11];
            System.arraycopy(str1Bytes, 0, str2Bytes, 0, str1Bytes.length);
            str2Bytes[9] = (byte) 0xC2;
            str2Bytes[10] = (byte) 0xA0;
            String noBreakSpace = new String(str2Bytes, StandardCharsets.UTF_8);
            System.out.println("带有C2 A0 -> NO-BREAK SPACE的字符串:" + noBreakSpace);
            System.out.println("使用trim无法去掉C2 A0 -> NO-BREAK SPACE:" + noBreakSpace.trim());
    
            // 32为我们平常谈论的Space空格 -> SPACE
            byte[] bytes1 = new byte[]{(byte) 0x20};
            String space1 = new String(bytes1, StandardCharsets.UTF_8);
            System.out.println("UTF-8 字符编码号32 -> 0x1F 输出:" + space1);
    
            // 0xC2=194 0xA0=160  -> NO-BREAK SPACE
            byte[] bytes2 = new byte[]{(byte) 0xC2, (byte) 0xA0};
            String space2 = new String(bytes2, StandardCharsets.UTF_8);
            char[] chars3 = space2.toCharArray();
            System.out.println("UTF-8 字符编码号194 -> 0xC2 160 -> 0xA0 输出:" + space2);
    
            byte[] bytes3 = new byte[]{(byte) 0xC2, (byte) 0xA0};
            String c2a0Space = new String(bytes3, StandardCharsets.UTF_8);
            Pattern p = Pattern.compile(c2a0Space);
            Matcher m = null;
            m = p.matcher(noBreakSpace);
            noBreakSpace = m.replaceAll("");
            System.out.println("使用正则去掉C2 A0 -> NO-BREAK SPACE:" + noBreakSpace);
        }
    }
    

      

    如果对您有帮助,请不要忘了给翎野君点赞。  

  • 相关阅读:
    self 和 super 关键字
    NSString类
    函数和对象方法的区别
    求两个数是否互质及最大公约数
    TJU Problem 1644 Reverse Text
    TJU Problem 2520 Quicksum
    TJU Problem 2101 Bullseye
    TJU Problem 2548 Celebrity jeopardy
    poj 2586 Y2K Accounting Bug
    poj 2109 Power of Cryptography
  • 原文地址:https://www.cnblogs.com/lingyejun/p/13056754.html
Copyright © 2011-2022 走看看