UTF8 Unicode 区别联系,UFT8 字符串Trim函数

最近项目中要将文档标题写入oracle数据库,编码是UTF8的,老报 字符串未正确结束这个错。   ORA-01756:括号内的字符串没有正确结束。

客户端,服务器的NLS_LANG都正确设置为了UTF8. 

将标题按照自己的顺序输出,我一个一个字符编码去查,发现标题后面多了一个'E5' 字节。这个是一个三字节UTF8编码的前缀,后面没有后续字节了,ORACLE当然报错。。

在公布解决方法前,复习下UTF8编码:

UTF8和Ascii 是兼容编码,UTF8和Unicode是一一对应的。 

一字节的为: 0*******

二字节的为: 110*****   10****** 

三字节的为: 1110****   10******  10******   

依次内推  4 5 6字节。其中*为有效字符编码

到这不经有个疑问了?为什么会有 6个字节的utf8? unicode 不是两个字节么?这样表示的unicode不是超过16个bit了?

原来unicode有4字节编码的方式。只是比较少见。(不见得,我测试了20000篇文档,其中就有出现) 

原问题的解决方法:

1.将数据库字符集改为 AL32UTF8。原因是 AL32UTF8支持更高版本的unicode.容错性强一点

2.写一个utf8_trim函数,将字符串中的非utf8编码去掉,替换成空格。然后入库。

 

我采用了第二种解决方法,写了一个utf8_trim,没有用循环,而用了大量丑陋的if else

主要考虑,一是比较简单,直观。还有就是效率高一点。因为,大部分的utf8是3字节,这样效率会高一点。

代码我初步测试过了,欢迎报bug 

 贴代码如下: 

  void trim_utf8(  char* str)

{
    
if (str  ==  NULL)
        
return  ;
    
int  length  =  strlen(str);
    
int  i  =   0 ;
    
while (i  <  length)
    {
        
if (str[i] > 0 )
        {
            i
++ ;
            
continue ;
        }
        
if (((unsigned  char ) str[i] & 0xE0 ==   192 ) // 110 2byte
        {
            
if  ((i + 1 ) <  length)
            {
                
if (((unsigned  char )(str[i + 1 ] & 0xC0 ))  !=   128 ) // 10
                {str[i]  =   '   ' ; i  =  i  + 1 ;} // invalid
                 else
                {i
=  i  + 2 ;}
            }
            
else // invalid
            {
                str[i]
= '   ' ;
            }
            
continue ;
        }
        
if (((unsigned  char ) str[i] & 0xC0 ==   128 ) // 10
        {
            str[i] 
=   '   ' ;
            i
++ ;
            
continue ;
        }
        
        
if (((unsigned  char )(str[i] & 0xF0 ))  ==   224 ) // 1110 3byte
        {
            
if  ((i + 2 ) <  length)
            {
                
if (((unsigned  char )(str[i + 1 ] & 0xC0 ))  !=   128   ||  ((unsigned  char )(str[i + 2 ] & 0xC0 ))  !=   128  ) // 10
                {
                    str[i] 
=   '   ' ;
                    
if  (((unsigned  char )(str[i + 1 ] & 0xC0 ))  !=   128 )
                    {i 
=  i + 1 ;}
                    
else
                    {str[i
+ 1 =   '   ' ;i  =  i  + 2 ;}
                }
                
else
                {
                    i
=  i  + 3 ;
                }
            }
            
else
            {
                
for  ( ;i  < length;i ++ )
                    str[i]
= '   ' ;
            }
            
continue ;
        }
        
if (((unsigned  char )(str[i] & 0xF8 ))  ==   240 ) // 11110 4byte
        {
            
if  ((i + 3 ) <  length)
            {

                
if (((unsigned  char )(str[i + 1 ] & 0xC0 ))  !=   128   ||  ((unsigned  char )(str[i + 2 ] & 0xC0 ))  !=   128   ||  ((unsigned  char )(str[i + 3 ] & 0xC0 ))  !=   128 ) // 10
                {
                    
int  j   =   0 ;
                    
for  ( j  =  i + 1 ;j <=  i + 3 ;j ++ )
                    { 
                        
if (((unsigned  char )(str[j] & 0xC0 ))  ==   128
                            str[j
- 1 =   '   '
                        
else
                            
break ;
                    }
                    i 
=  j;
                }
                
else
                {
                    i
=  i  + 4 ;
                }
            }
            
else
            {
                
for  ( ;i  < length;i ++ )
                    str[i]
= '   ' ;
            }
            
continue ;
        }
        
if (((unsigned  char )(str[i] & 0xFC ))  ==   248 ) // 111110 5byte
        {
            
if  ((i + 4 ) <  length)
            {

                
if (((unsigned  char )(str[i + 1 ] & 0xC0 ))  !=   128   ||  ((unsigned  char )(str[i + 2 ] & 0xC0 ))  !=   128   ||  ((unsigned  char )(str[i + 3 ] & 0xC0 ))  !=   128 ||  ((unsigned  char )(str[i + 4 ] & 0xC0 ))  !=   128 ) // 10
                {
                    
int  j   =   0 ;
                    
for  ( j  =  i + 1 ;j <=  i + 4 ;j ++ )
                    { 
                        
if (((unsigned  char )(str[j] & 0xC0 ))  ==   128
                            str[j
- 1 =   '   '
                        
else
                            
break ;
                    }
                    i 
=  j;
                }
                
else
                {
                    i
=  i  + 5 ;
                }
            }
            
else
            {
                
for  ( ;i  < length;i ++ )
                    str[i]
= '   ' ;
            }
            
continue ;
        }
        
if (((unsigned  char )(str[i] & 0xFE ))  ==   252 ) // 1111110 6byte
        {
            
if  ((i + 5 ) <  length)
            {
                
if (((unsigned  char )(str[i + 1 ] & 0xC0 ))  !=   128   ||  ((unsigned  char )(str[i + 2 ] & 0xC0 ))  !=   128   ||  ((unsigned  char )(str[i + 3 ] & 0xC0 ))  !=   128 ||  ((unsigned  char )(str[i + 4 ] & 0xC0 ))  !=   128 ||  ((unsigned  char )(str[i + 5 ] & 0xC0 ))  !=   128 ) // 10
                {
                    
int  j   =   0 ;
                    
for  ( j  =  i + 1 ;j <=  i + 5 ;j ++ )
                    { 
                        
if (((unsigned  char )(str[j] & 0xC0 ))  ==   128
                            str[j
- 1 =   '   '
                        
else
                            
break ;
                    }
                    i 
=  j;
                }
                
else
                {
                    i
=  i  + 6 ;
                }
            }
            
else
            {
                
for  ( ;i  < length;i ++ )
                    str[i]
= '   ' ;
            }
            
continue ;
        }
        str[i]
= '   ' ;
        i
++ ;
    }

}

 

 

 

 

转载于:https://www.cnblogs.com/davidluo/articles/1786471.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值