Java String类型含普通字符以及中文字符,计算等价的中文字符串长度

/*
    获取中文字符串的长度
    我的12 = 3
    我的1 = 3
    我的123456 = 5
 */
public int getChineseStrLen(String str) throws UnsupportedEncodingException {
    int ULen = str.getBytes("utf-8").length;
    int len = str.length();
    int CLen = (ULen - len) / 2;
    return CLen + (len - CLen + 1) / 2;
}

问题描述:

        向Oracle数据库中一varchar2(64)类型字段中插入一条String类型数据,程序使用String.length()来进行数据的长度校验,如果数据是纯英文,没有问题,但是如果数据中包含中文,校验可以通过,但是在数据入库时经常会报数据超长。

问题分析:

        既然问题是数据超长,那么问题应该就是出在数据长度校验上,也就是出在String.length()这个方法上,来看看JDK是如何描述这个方法的:

[plain] view plain copy

  1. length  
  2. public int length()返回此字符串的长度。长度等于字符串中 Unicode 代码单元的数量。   
  3. 指定者:  
  4. 接口 CharSequence 中的 length  
  5. 返回:  
  6. 此对象表示的字符序列的长度。  

[java] view plain copy

  1. public static void main(String[] args) throws UnsupportedEncodingException {  
  2.     String a = "123abc";  
  3.     System.out.println(a.length());  
  4.     a = "中文";  
  5.     System.out.println(a.length());  
  6. }  

结果为6和2。这个方法判断的是String串的字符长度,但是Oracle数据库中却是以字节来判断varchar2类型数据长度(如:字段定义为varchar2(64),则存入该字段的字符串的字节长度不得超过64)。如果String串为纯英文,那么一个英文字母是一个字符,长度为1,占1个字节,不会出错,但如果String串中包含中文,一个中文汉字也是一个字符,长度为1,但是却占多个字节(具体占几个字节跟使用的编码有关),如果数据中包含中文,数据的长度就很有可能会超过数据库中对应字段的长度限制

不同数据库对字符串类型数据长度的计算方式不同,如:MySQL数据库中以字符长度来判断varchar类型数据的长度(如:字段定义varchar,长度定为64,小数位定义为0,则存入该字段的字符串的字符长度不得超过64)

解决方式:

        既然是判断数据长度时以字符为标准导致出错,那么思路就很明确了,在进行数据长度校验时,取数据的字节长度:

[java] view plain copy

  1. public static void main(String[] args) throws UnsupportedEncodingException {  
  2.     String a = "123abc";  
  3. int num = a.getBytes("utf-8").length;  
  4.     System.out.println(num);  
  5.     a = "中文";  
  6.     num = a.getBytes("utf-8").length;  
  7.     System.out.println(num);  
  8. }  

结果为6和6,为什么转换成utf-8呢,因为数据库使用的是utf-8编码,既然数据最终是要存到数据库中,那么首先先要保证数据在程序中时、在数据库中时的编码一致(同一个字符在不同的编码格式中所占的字节位数不一致,这点很关键),然后再保证程序和数据库判断数据长度的方式一致,才能避免程序校验通过,入库时却提示数据长度超长的问题

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏AzMark

Python 学习笔记之类与实例

类 (class) 封装一组相关数据,使之成为一个整体,并使用一种方法持续展示和维护。

5410
来自专栏liulun

Nim教程【十五】【完结】

模版 模版是Nim语言中的抽象语法树,它是一种简单的替换机制,在编译期被处理 这个特性使Nim语言可以和C语言很好的运行在一起 像调用一个方法一样调用一个模版 ...

24580
来自专栏Jerry的SAP技术分享

使用javap深入理解Java整型常量和整型变量的区别

下面我们就用javap将.class文件反编译出来然后深入研究Java里整型变量和整型常量的区别。

15930
来自专栏lgp20151222

理解一下策略模式,工厂模式

开发遇到了一个工厂模式和策略模式合起来的代码,觉得真的是写的太好了,所以打算了解下这两个模式的区别。

13910
来自专栏编程

PHP漏洞函数总结

1.MD5 compare漏洞 PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每一个以”0E”开头的哈希值都解释为0,所以如果两个不...

40470
来自专栏用户2442861的专栏

Java中Synchronized的用法

原文:http://blog.csdn.net/luoweifu/article/details/46613015 作者:luoweifu 转载请标名...

8310
来自专栏web后端

PHP json中的Malformed UTF-8 characters问题

一般情形下,json嵌套层级太深这种失败是罕见,但是又相对比较容易识别的;另外一种错误,是关于utf-8编码的,则情形相对比较复杂;

83860
来自专栏小勇DW3

设计模式--代理模式(附源码分析)

 在平时的开发过程中,我们实现方法的调用往往只是普通的对象调用方法,实现复杂的业务就是一层一层的对象调用方法依次进行实现,但是如果我要实现在某些方法执行前或者...

24830
来自专栏微信公众号:Java团长

Java动态代理原理及解析

代理模式是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个真实对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类...

10640
来自专栏逆向技术

C++反汇编第二讲,不同作用域下的构造和析构的识别

               C++反汇编第二讲,不同作用域下的构造和析构的识别 目录大纲:   1.全局(静态)对象的识别,(全局静态全局一样的,都是编译期间...

210100

扫码关注云+社区

领取腾讯云代金券