• C#、Java实现按字节截取字符串包含中文汉字和英文字符数字标点符号等


    C#、Java实现按字节截取字符串,字符串中包含中文汉字和英文字符数字标点符号等。

    在实际项目应用过程中,尤其是在web开发时可能遇到的比较多,就以我的(JiYF笨小孩管理系统)为例,再发布文章时候,文章摘要如果用户没有填写,默认截取文章前面255个字节,这个时候里面难免包含中文汉字,英文字母,标点符号等等有可能就会遇到截取出半个汉字的情况。

    以Unicode 16(UCS2)编码为例,每一个字符占用俩个字节

    假如字符串s:

    String s = "潮哥shuo丑安ni去哪?"; 

    上面的s字符串既有汉字,又有英文字符和数字

    举例:

    如果要截取前6个字节的字符,应该是”潮哥sh",但如果用substring方法截取前6个字符就成了"潮哥shuo"。

    如果截取9个字节,应该是“潮哥shuo” 丑的半个汉字就去掉了,但如果用substring方法截取前9个字符就成了"潮哥shuo丑安n"。

    产生这个问题的原因是将substring方法将双字节的汉字当成一个字节的字符(UCS2字符)处理了。 要解决这个问题的方法是首先得到该字符串的UCS2编码的字节数组,如下面的代码如下:

    C#代码示例:

     1 private static string cutSubstring(string str, int length)
     2         {
     3             if (str == null || str.Length == 0 || length < 0)
     4             { 
     5                 return ""; 
     6             }
     7 
     8             byte[] bytes = System.Text.Encoding.Unicode.GetBytes(str);
     9             int n = 0;  //  表示当前的字节数
    10             int i = 0;  //  要截取的字节数
    11             for (; i < bytes.GetLength(0) && n < length; i++)
    12             {
    13                 //  偶数位置,如0、2、4等,为UCS2编码中两个字节的第一个字节
    14                 if (i % 2 == 0)
    15                 {
    16                     n++;      //  在UCS2第一个字节时n加1
    17                 }
    18                 else
    19                 {
    20                     //  当UCS2编码的第二个字节大于0时,该UCS2字符为汉字,一个汉字算两个字节
    21                     if (bytes[i] > 0)
    22                     {
    23                         n++;
    24                     }
    25                 }
    26             }
    27             //  如果i为奇数时,处理成偶数
    28             if (i % 2 == 1)
    29             {
    30                 //  该UCS2字符是汉字时,去掉这个截一半的汉字
    31                 if (bytes[i] > 0)
    32                     i = i - 1;
    33                 //  该UCS2字符是字母或数字,则保留该字符
    34                 else
    35                     i = i + 1;
    36             }
    37             return System.Text.Encoding.Unicode.GetString(bytes, 0, i);
    38         }

    分析:

    测试结果:

    调用

    cutSubstring("潮哥shuo丑安ni去哪?",6);------>运行结果:“潮哥sh”
    cutSubstring("潮哥shuo丑安ni去哪?",9);------>运行结果:“潮哥shuo”

    Java代码示例:

    (细心的童鞋会发现i值不同,java是从2开始C#从0开始,这里注意,java转换为字节数组,前俩个字节是标志位,所以第0位和第1位是标志位,从2开始)

     1 public static String bSubstring(String s, int length) throws Exception
     2     {
     3 
     4         byte[] bytes = s.getBytes("Unicode");
     5         int n = 0; // 表示当前的字节数
     6         int i = 2; // 要截取的字节数,从第3个字节开始
     7         for (; i < bytes.length && n < length; i++)
     8         {
     9             // 奇数位置,如3、5、7等,为UCS2编码中两个字节的第二个字节
    10             if (i % 2 == 1)
    11             {
    12                 n++; // 在UCS2第二个字节时n加1
    13             }
    14             else
    15             {
    16                 // 当UCS2编码的第一个字节不等于0时,该UCS2字符为汉字,一个汉字算两个字节
    17                 if (bytes[i] != 0)
    18                 {
    19                     n++;
    20                 }
    21             }
    22         }
    23         // 如果i为奇数时,处理成偶数
    24         if (i % 2 == 1)
    25 
    26         {
    27             // 该UCS2字符是汉字时,去掉这个截一半的汉字
    28             if (bytes[i - 1] != 0)
    29                 i = i - 1;
    30             // 该UCS2字符是字母或数字,则保留该字符
    31             else
    32                 i = i + 1;
    33         }
    34 
    35         return new String(bytes, 0, i, "Unicode");
    36     }

    测试结果:

    调用

    cutSubstring("潮哥shuo丑安ni去哪?",6);------>运行结果:“潮哥sh”
    cutSubstring("潮哥shuo丑安ni去哪?",9);------>运行结果:“潮哥shuo”
  • 相关阅读:
    Entity Framework with NOLOCK
    读取的XML节点中带有冒号怎么办?
    一道数学运算题
    mock基本使用
    json-server基本使用
    axios、ajax、fetch三者的区别
    深入响应式原理
    vue组件传值
    递归与循环的区别
    undefined 和null的区别
  • 原文地址:https://www.cnblogs.com/JiYF/p/6543779.html
Copyright © 2020-2023  润新知